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.CarrierReconciliationInMapper;
import com.ga.core.mapper.commission.IncomeCommissionLedgerMapper;
import com.ga.core.vo.commission.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

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

    private final CarrierReconciliationInMapper mapper;
    private final IncomeCommissionLedgerMapper incomeMapper;

    public PageResponse<CarrierReconciliationInResp> list(CarrierReconciliationInSearchParam param) {
        param.startPage();
        return PageResponse.of(mapper.selectList(param));
    }

    public CarrierReconciliationInResp detail(Long reconId) {
        CarrierReconciliationInResp resp = mapper.selectById(reconId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    /**
     * 대사 등록 — reported_total 입력, status = RECEIVED.
     */
    @Transactional
    public Long create(CarrierReconciliationInSaveReq req) {
        CarrierReconciliationInVO vo = new CarrierReconciliationInVO();
        vo.setCompanyId(req.getCompanyId());
        vo.setSettleMonth(req.getSettleMonth());
        vo.setFileName(req.getFileName());
        vo.setRecordCount(req.getRecordCount() != null ? req.getRecordCount() : 0);
        vo.setReportedTotal(req.getReportedTotal());
        vo.setSystemTotal(BigDecimal.ZERO);
        vo.setVarianceAmount(BigDecimal.ZERO);
        vo.setStatus("RECEIVED");
        vo.setCreatedBy(SecurityUtil.getCurrentUserId());
        mapper.insert(vo);
        return vo.getReconId();
    }

    /**
     * 대사 실행 — system_total = income_commission 집계, variance = reported − system.
     * |variance| < 1 이면 MATCHED, 아니면 VARIANCE.
     */
    @Transactional
    public void reconcile(Long reconId) {
        CarrierReconciliationInResp resp = mapper.selectById(reconId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        if ("APPROVED".equals(resp.getStatus())) throw new BizException(ErrorCode.INVALID_PARAMETER);

        BigDecimal systemTotal = incomeMapper.sumByCarrierAndMonth(
                resp.getCompanyId(), resp.getSettleMonth());
        if (systemTotal == null) systemTotal = BigDecimal.ZERO;

        BigDecimal variance = resp.getReportedTotal().subtract(systemTotal);
        String newStatus = variance.abs().compareTo(BigDecimal.ONE) < 0 ? "MATCHED" : "VARIANCE";

        CarrierReconciliationInVO vo = buildVO(resp);
        vo.setSystemTotal(systemTotal);
        vo.setVarianceAmount(variance);
        vo.setStatus(newStatus);
        mapper.update(vo);
    }

    /**
     * 승인 처리 — status = APPROVED.
     */
    @Transactional
    public void approve(Long reconId) {
        CarrierReconciliationInResp resp = mapper.selectById(reconId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        if ("RECEIVED".equals(resp.getStatus())) throw new BizException(ErrorCode.INVALID_PARAMETER);
        CarrierReconciliationInVO vo = buildVO(resp);
        vo.setStatus("APPROVED");
        mapper.update(vo);
    }

    private CarrierReconciliationInVO buildVO(CarrierReconciliationInResp resp) {
        CarrierReconciliationInVO vo = new CarrierReconciliationInVO();
        vo.setReconId(resp.getReconId());
        vo.setCompanyId(resp.getCompanyId());
        vo.setSettleMonth(resp.getSettleMonth());
        vo.setFileName(resp.getFileName());
        vo.setRecordCount(resp.getRecordCount());
        vo.setReportedTotal(resp.getReportedTotal());
        vo.setSystemTotal(resp.getSystemTotal());
        vo.setVarianceAmount(resp.getVarianceAmount());
        vo.setStatus(resp.getStatus());
        return vo;
    }
}
