package com.ga.batch.settlement.domain;

import com.ga.core.mapper.ledger.MaintainLedgerMapper;
import com.ga.core.mapper.ledger.RecruitLedgerMapper;
import com.ga.core.mapper.regulatory.RegulatoryLimitMapper;
import com.ga.core.vo.regulatory.RegulatoryLimitVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * 배치용 1200%룰 한도 체커. ga-api RegulatoryLimitChecker와 동일 로직.
 */
@Component
@RequiredArgsConstructor
public class BatchRegulatoryLimitChecker {

    private static final String TOTAL_RATIO = "TOTAL_RATIO";
    private static final String FIRST_YEAR_RATIO = "FIRST_YEAR_RATIO";
    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final RegulatoryLimitMapper limitMapper;
    private final RecruitLedgerMapper recruitLedgerMapper;
    private final MaintainLedgerMapper maintainLedgerMapper;

    /** 누적 수수료율 한도 체크 (1200%). 신계약 + 유지 원장 합산. */
    public ViolationResult checkContractTotal(Long contractId, BigDecimal additionalAmount, LocalDate baseDate) {
        String baseDateStr = baseDate.format(DATE_FMT);
        RegulatoryLimitVO limit = limitMapper.selectActiveByType(TOTAL_RATIO, null, baseDateStr);
        if (limit == null) {
            return ViolationResult.ok(additionalAmount, null, TOTAL_RATIO);
        }

        BigDecimal currentTotal = sumPaidByContract(contractId);
        BigDecimal projected = currentTotal.add(additionalAmount);

        if (projected.compareTo(limit.getLimitValue()) > 0) {
            return ViolationResult.violated(
                    currentTotal,
                    limit.getLimitValue(),
                    TOTAL_RATIO,
                    String.format("누적 수수료 한도 초과: 현재 %s, 추가 %s, 한도 %s %s",
                            currentTotal, additionalAmount, limit.getLimitValue(), limit.getUnit())
            );
        }
        return ViolationResult.ok(currentTotal, limit.getLimitValue(), TOTAL_RATIO);
    }

    /** 1차년 수수료율 한도 체크. */
    public ViolationResult checkFirstYear(Long contractId, BigDecimal additionalAmount, LocalDate baseDate) {
        String baseDateStr = baseDate.format(DATE_FMT);
        RegulatoryLimitVO limit = limitMapper.selectActiveByType(FIRST_YEAR_RATIO, null, baseDateStr);
        if (limit == null) {
            return ViolationResult.ok(additionalAmount, null, FIRST_YEAR_RATIO);
        }

        BigDecimal currentTotal = nullSafe(recruitLedgerMapper.sumFirstYearByContract(contractId));
        BigDecimal projected = currentTotal.add(additionalAmount);

        if (projected.compareTo(limit.getLimitValue()) > 0) {
            return ViolationResult.violated(
                    currentTotal,
                    limit.getLimitValue(),
                    FIRST_YEAR_RATIO,
                    String.format("1차년 수수료 한도 초과: 현재 %s, 추가 %s, 한도 %s %s",
                            currentTotal, additionalAmount, limit.getLimitValue(), limit.getUnit())
            );
        }
        return ViolationResult.ok(currentTotal, limit.getLimitValue(), FIRST_YEAR_RATIO);
    }

    private BigDecimal sumPaidByContract(Long contractId) {
        return nullSafe(recruitLedgerMapper.sumByContract(contractId))
                .add(nullSafe(maintainLedgerMapper.sumByContract(contractId)));
    }

    private BigDecimal nullSafe(BigDecimal v) {
        return v != null ? v : BigDecimal.ZERO;
    }
}
