package com.ga.batch.settlement.step;

import com.ga.batch.settlement.SettlementContext;
import com.ga.batch.settlement.domain.BatchChargebackCalculator;
import com.ga.batch.settlement.domain.ChargebackResult;
import com.ga.common.util.DateUtil;
import com.ga.core.mapper.ledger.RecruitLedgerMapper;
import com.ga.core.mapper.product.ContractMapper;
import com.ga.core.mapper.settle.ChargebackMapper;
import com.ga.core.vo.product.ContractResp;
import com.ga.core.vo.product.ContractSearchParam;
import com.ga.core.vo.settle.ChargebackVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.stereotype.Component;

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

/**
 * Step 6 — chargebackException: 환수 자동생성 + 예외금액 자동계산
 *
 * 환수율 계산: BatchChargebackCalculator (chargeback_grade 5단계 차등환수) 사용.
 * 환수 원금: 해당 계약의 모집 원장 합산 (recruit_ledger 기준).
 */
@Slf4j
@Component
@JobScope
@RequiredArgsConstructor
public class ChargebackExceptionStep implements Tasklet {

    private final SettlementContext ctx;
    private final ContractMapper contractMapper;
    private final RecruitLedgerMapper recruitMapper;
    private final ChargebackMapper chargebackMapper;
    private final BatchChargebackCalculator chargebackCalculator;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
        log.info("[Step6 chargebackException] settleMonth={}", ctx.getSettleMonth());

        ContractSearchParam param = new ContractSearchParam();
        param.setStatus("LAPSE");
        param.setPageSize(Integer.MAX_VALUE);
        List<ContractResp> lapsed = contractMapper.selectList(param);

        List<ChargebackVO> chargebacks = new ArrayList<>();
        for (ContractResp c : lapsed) {
            if (c.getLapseDate() == null || c.getContractDate() == null) continue;

            String lapseMonth = DateUtil.getSettleMonth(c.getLapseDate());
            if (!ctx.getSettleMonth().equals(lapseMonth)) continue;

            // 모집 원장에서 원 수수료 조회
            BigDecimal originalCommission = recruitMapper.sumByContract(c.getContractId());
            if (originalCommission == null || originalCommission.signum() <= 0) continue;

            // BatchChargebackCalculator: chargeback_grade 5단계 차등환수
            ChargebackResult result = chargebackCalculator.calculate(
                    c.getContractDate(), c.getLapseDate(),
                    originalCommission, c.getInsuranceType());

            if (result.chargebackAmount().signum() <= 0) continue;

            ChargebackVO cb = new ChargebackVO();
            cb.setContractId(c.getContractId());
            cb.setAgentId(c.getAgentId());
            cb.setPolicyNo(c.getPolicyNo());
            cb.setLapseMonth(result.monthsElapsed());
            cb.setCbRate(result.appliedPercent());
            cb.setCbAmount(result.chargebackAmount());
            cb.setRemainAmount(result.chargebackAmount());
            cb.setSettleMonth(ctx.getSettleMonth());
            cb.setStatus("NEW");
            chargebacks.add(cb);
        }

        if (!chargebacks.isEmpty()) {
            chargebackMapper.insertBatch(chargebacks);
        }
        ctx.setChargebackCount(chargebacks.size());
        log.info("[Step6] chargeback inserted: {} (using BatchChargebackCalculator)", chargebacks.size());
        return RepeatStatus.FINISHED;
    }
}
