package com.ga.api.service.commission;

import com.ga.common.exception.BizException;
import com.ga.common.exception.ErrorCode;
import com.ga.common.model.PageResponse;
import com.ga.core.mapper.commission.ProductConversionRateMapper;
import com.ga.core.mapper.commission.RecognizedPerformanceLedgerMapper;
import com.ga.core.vo.commission.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class RecognizedPerformanceService {

    private final ProductConversionRateMapper conversionRateMapper;
    private final RecognizedPerformanceLedgerMapper ledgerMapper;

    // ── Product Conversion Rate (rule) ────────────────────────────────────────

    public PageResponse<ProductConversionRateResp> listRates(ProductConversionRateSearchParam param) {
        param.startPage();
        return PageResponse.of(conversionRateMapper.selectList(param));
    }

    public ProductConversionRateResp detailRate(Long rateId) {
        ProductConversionRateResp resp = conversionRateMapper.selectById(rateId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    @Transactional
    public Long createRate(ProductConversionRateSaveReq req) {
        ProductConversionRateVO vo = new ProductConversionRateVO();
        vo.setProductId(req.getProductId());
        vo.setConversionRate(req.getConversionRate());
        vo.setEffectiveFrom(req.getEffectiveFrom());
        vo.setEffectiveTo(req.getEffectiveTo());
        conversionRateMapper.insert(vo);
        return vo.getRateId();
    }

    @Transactional
    public void updateRate(Long rateId, ProductConversionRateSaveReq req) {
        ProductConversionRateResp resp = conversionRateMapper.selectById(rateId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        ProductConversionRateVO vo = new ProductConversionRateVO();
        vo.setRateId(rateId);
        vo.setProductId(req.getProductId());
        vo.setConversionRate(req.getConversionRate());
        vo.setEffectiveFrom(req.getEffectiveFrom());
        vo.setEffectiveTo(req.getEffectiveTo());
        conversionRateMapper.update(vo);
    }

    @Transactional
    public void deleteRate(Long rateId) {
        ProductConversionRateResp resp = conversionRateMapper.selectById(rateId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        conversionRateMapper.delete(rateId);
    }

    // ── Ledger ────────────────────────────────────────────────────────────────

    public PageResponse<RecognizedPerformanceLedgerResp> listLedgers(RecognizedPerformanceLedgerSearchParam param) {
        param.startPage();
        return PageResponse.of(ledgerMapper.selectList(param));
    }

    public RecognizedPerformanceLedgerResp detailLedger(Long ledgerId) {
        RecognizedPerformanceLedgerResp resp = ledgerMapper.selectById(ledgerId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    @Transactional
    public Long createLedger(RecognizedPerformanceLedgerSaveReq req) {
        // 환산보험료 = premium × conversion_rate
        BigDecimal convertedPremium = req.getPremiumAmount()
                .multiply(req.getConversionRate())
                .setScale(2, RoundingMode.HALF_UP);
        // 인정실적 = converted_premium × recognition_rate
        BigDecimal recognizedAmount = convertedPremium
                .multiply(req.getRecognitionRate())
                .setScale(2, RoundingMode.HALF_UP);

        RecognizedPerformanceLedgerVO vo = new RecognizedPerformanceLedgerVO();
        vo.setAgentId(req.getAgentId());
        vo.setContractId(req.getContractId());
        vo.setSettleMonth(req.getSettleMonth());
        vo.setPremiumAmount(req.getPremiumAmount());
        vo.setConversionRate(req.getConversionRate());
        vo.setConvertedPremium(convertedPremium);
        vo.setRecognitionRate(req.getRecognitionRate());
        vo.setRecognizedAmount(recognizedAmount);
        vo.setStatus("CALCULATED");
        ledgerMapper.insert(vo);
        return vo.getLedgerId();
    }
}
