package com.ga.core.mapper.commission;

import com.ga.core.vo.commission.ClawbackReceivableResp;
import com.ga.core.vo.commission.ClawbackReceivableSearchParam;
import com.ga.core.vo.commission.ClawbackReceivableVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * clawback_receivable Mapper — 환수채권 마스터 (V111)
 */
@Mapper
public interface ClawbackReceivableMapper {

    /** 단건 조회 — 설계사명 조인 + 회수이력(collection) 포함 */
    ClawbackReceivableResp selectById(@Param("receivableId") Long receivableId);

    /** 목록 조회 — PageHelper 호환, 설계사명 조인 포함 */
    List<ClawbackReceivableResp> selectList(ClawbackReceivableSearchParam param);

    /** 설계사 + 발생월 단건 조회 (배치 결과 확인용) */
    ClawbackReceivableVO selectByAgentMonth(@Param("agentId") Long agentId,
                                            @Param("originSettleMonth") String originSettleMonth);

    /**
     * 배치 priorBalance 조회.
     * SUM(balance) WHERE agent_id=? AND status IN('OUTSTANDING','RECOVERING')
     *              AND origin_settle_month < #{settleMonth}
     * 당월 발생분 자기상계 방지용 — null 이면 0 반환.
     */
    BigDecimal outstandingBalance(@Param("agentId") Long agentId,
                                  @Param("settleMonth") String settleMonth);

    /**
     * FIFO 회수 대상 채권 목록.
     * status IN('OUTSTANDING','RECOVERING') AND origin_settle_month < settleMonth
     * ORDER BY origin_settle_month ASC, receivable_id ASC
     */
    List<ClawbackReceivableVO> selectOutstandingByAgentFifo(@Param("agentId") Long agentId,
                                                             @Param("settleMonth") String settleMonth);

    /**
     * 배치 멱등 upsert.
     * INSERT ... ON CONFLICT(agent_id, origin_settle_month) DO UPDATE
     * SET original_amount=EXCLUDED, balance=EXCLUDED, recovered_amount=0,
     *     status='OUTSTANDING', updated_at=now()
     */
    int upsertCarryover(ClawbackReceivableVO vo);

    /**
     * 회수 반영 업데이트.
     * recovered_amount, balance, status, last_recovery_month, updated_at 갱신.
     */
    int updateRecovery(@Param("receivableId") Long receivableId,
                       @Param("recoveredAmount") BigDecimal recoveredAmount,
                       @Param("balance") BigDecimal balance,
                       @Param("status") String status,
                       @Param("lastRecoveryMonth") String lastRecoveryMonth);

    /**
     * 대손/직접상환 처리.
     * balance→0, status, writeoff_reason, written_off_at, written_off_by, updated_at 갱신.
     */
    int writeOff(@Param("id") Long id,
                 @Param("status") String status,
                 @Param("reason") String reason,
                 @Param("userId") Long userId);

    /**
     * 설계사별 미결 잔액 집계 (summary API용).
     * status IN('OUTSTANDING','RECOVERING') 대상.
     */
    List<Map<String, Object>> summaryByAgent(ClawbackReceivableSearchParam param);

    int countByCondition(ClawbackReceivableSearchParam param);
}
