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.common.util.SecurityUtil;
import com.ga.core.mapper.commission.CommissionSimulationMapper;
import com.ga.core.vo.commission.CommissionSimulationResp;
import com.ga.core.vo.commission.CommissionSimulationSaveReq;
import com.ga.core.vo.commission.CommissionSimulationSearchParam;
import com.ga.core.vo.commission.CommissionSimulationVO;
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 CommissionSimulationService {

    private static final BigDecimal WITHHOLDING_TAX_RATE = new BigDecimal("0.033");
    private static final BigDecimal DEFAULT_CHARGEBACK_RATE = new BigDecimal("0.5");

    private final CommissionSimulationMapper simulationMapper;

    public PageResponse<CommissionSimulationResp> list(CommissionSimulationSearchParam param) {
        param.startPage();
        return PageResponse.of(simulationMapper.selectList(param));
    }

    public CommissionSimulationResp detail(Long simId) {
        CommissionSimulationResp resp = simulationMapper.selectById(simId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    /**
     * 수수료 시뮬레이션 계산 후 저장·반환.
     * company_payment  = premium × company_rate
     * agent_commission = company_payment × payout_rate
     * withholding_tax  = agent_commission × 3.3%
     * net_amount       = agent_commission − withholding_tax
     * expected_chargeback: 입력 값이 있으면 사용, 없으면 agent_commission × 50% (13개월 가정)
     * 모든 금액 setScale(2, HALF_UP).
     */
    @Transactional
    public CommissionSimulationResp simulate(CommissionSimulationSaveReq req) {
        BigDecimal companyPayment = req.getPremiumAmount()
                .multiply(req.getCompanyRate())
                .setScale(2, RoundingMode.HALF_UP);

        BigDecimal agentCommission = companyPayment
                .multiply(req.getPayoutRate())
                .setScale(2, RoundingMode.HALF_UP);

        BigDecimal withholdingTax = agentCommission
                .multiply(WITHHOLDING_TAX_RATE)
                .setScale(2, RoundingMode.HALF_UP);

        BigDecimal netAmount = agentCommission
                .subtract(withholdingTax)
                .setScale(2, RoundingMode.HALF_UP);

        BigDecimal expectedChargeback;
        if (req.getExpectedChargeback() != null) {
            expectedChargeback = req.getExpectedChargeback().setScale(2, RoundingMode.HALF_UP);
        } else {
            expectedChargeback = agentCommission
                    .multiply(DEFAULT_CHARGEBACK_RATE)
                    .setScale(2, RoundingMode.HALF_UP);
        }

        CommissionSimulationVO vo = new CommissionSimulationVO();
        vo.setSimName(req.getSimName());
        vo.setPremiumAmount(req.getPremiumAmount());
        vo.setCompanyRate(req.getCompanyRate());
        vo.setPayoutRate(req.getPayoutRate());
        vo.setCommissionYear(req.getCommissionYear());
        vo.setCompanyPayment(companyPayment);
        vo.setAgentCommission(agentCommission);
        vo.setWithholdingTax(withholdingTax);
        vo.setNetAmount(netAmount);
        vo.setExpectedChargeback(expectedChargeback);
        vo.setCreatedBy(SecurityUtil.getCurrentUserId());
        simulationMapper.insert(vo);

        CommissionSimulationResp resp = simulationMapper.selectById(vo.getSimId());
        if (resp == null) throw new BizException(ErrorCode.INTERNAL_ERROR);
        return resp;
    }
}
