package com.ga.api.service.settle;

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.settle.TerminationSettlementMapper;
import com.ga.core.vo.settle.TermSettleStatus;
import com.ga.core.vo.settle.TerminationSettlementResp;
import com.ga.core.vo.settle.TerminationSettlementSaveReq;
import com.ga.core.vo.settle.TerminationSettlementSearchParam;
import com.ga.core.vo.settle.TerminationSettlementVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

    private final TerminationSettlementMapper termSettleMapper;

    public PageResponse<TerminationSettlementResp> list(TerminationSettlementSearchParam param) {
        param.startPage();
        return PageResponse.of(termSettleMapper.selectList(param));
    }

    public TerminationSettlementResp detail(Long termSettleId) {
        TerminationSettlementResp resp = termSettleMapper.selectById(termSettleId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    @Transactional
    public Long create(TerminationSettlementSaveReq req) {
        // 해당 설계사의 해촉 정산이 이미 있는지 확인
        TerminationSettlementVO existing = termSettleMapper.selectByAgent(req.getAgentId());
        if (existing != null && !TermSettleStatus.CANCELLED.name().equals(existing.getStatus())) {
            throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 처리 중인 해촉 정산이 있습니다");
        }

        TerminationSettlementVO vo = new TerminationSettlementVO();
        vo.setAgentId(req.getAgentId());
        vo.setTerminationDate(req.getTerminationDate());
        vo.setOrgHistoryId(req.getOrgHistoryId());
        vo.setCalcMonth(req.getCalcMonth());
        vo.setUnpaidRecruitAmount(req.getUnpaidRecruitAmount());
        vo.setUnpaidInstallmentAmount(req.getUnpaidInstallmentAmount());
        vo.setUnpaidIncentiveAmount(req.getUnpaidIncentiveAmount());
        vo.setChargebackExpectedAmount(req.getChargebackExpectedAmount());
        vo.setChargebackWaivedAmount(req.getChargebackWaivedAmount());
        vo.setDeductionAmount(req.getDeductionAmount());
        vo.setFinalPayAmount(req.getFinalPayAmount());
        vo.setNote(req.getNote());
        vo.setStatus(TermSettleStatus.CALCULATING.name());
        vo.setCreatedBy(SecurityUtil.getCurrentUserId());
        termSettleMapper.insert(vo);
        return vo.getTermSettleId();
    }

    @Transactional
    public void update(Long termSettleId, TerminationSettlementSaveReq req) {
        TerminationSettlementVO vo = termSettleMapper.selectVoById(termSettleId);
        if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
        if (!TermSettleStatus.CALCULATING.name().equals(vo.getStatus())) {
            throw new BizException(ErrorCode.INVALID_STATUS, "산출 중 상태만 수정 가능합니다");
        }

        vo.setUnpaidRecruitAmount(req.getUnpaidRecruitAmount());
        vo.setUnpaidInstallmentAmount(req.getUnpaidInstallmentAmount());
        vo.setUnpaidIncentiveAmount(req.getUnpaidIncentiveAmount());
        vo.setChargebackExpectedAmount(req.getChargebackExpectedAmount());
        vo.setChargebackWaivedAmount(req.getChargebackWaivedAmount());
        vo.setDeductionAmount(req.getDeductionAmount());
        vo.setFinalPayAmount(req.getFinalPayAmount());
        vo.setNote(req.getNote());
        vo.setUpdatedBy(SecurityUtil.getCurrentUserId());
        termSettleMapper.update(vo);
    }

    @Transactional
    public void confirm(Long termSettleId) {
        TerminationSettlementVO vo = termSettleMapper.selectVoById(termSettleId);
        if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
        if (!TermSettleStatus.CALCULATING.name().equals(vo.getStatus())) {
            throw new BizException(ErrorCode.INVALID_STATUS, "산출 중 상태만 확정 가능합니다");
        }
        termSettleMapper.updateStatus(termSettleId, TermSettleStatus.CONFIRMED.name(), SecurityUtil.getCurrentUserId());
    }

    /**
     * 해촉 시 자동 생성 처리 (POST /process).
     * agentId를 받아 CALCULATING 상태로 해촉 정산 레코드 생성.
     * 실제 금액 산출은 배치 또는 별도 update 호출로 완성.
     */
    @Transactional
    public Long process(TerminationSettlementSaveReq req) {
        return create(req);
    }
}
