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.AdvancePaymentMapper;
import com.ga.core.vo.commission.AdvancePaymentResp;
import com.ga.core.vo.commission.AdvancePaymentSaveReq;
import com.ga.core.vo.commission.AdvancePaymentSearchParam;
import com.ga.core.vo.commission.AdvancePaymentVO;
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 AdvancePaymentService {

    private final AdvancePaymentMapper mapper;

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

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

    /**
     * 선지급 등록 — balance = principal, status = OUTSTANDING.
     */
    @Transactional
    public Long create(AdvancePaymentSaveReq req) {
        AdvancePaymentVO vo = new AdvancePaymentVO();
        vo.setAgentId(req.getAgentId());
        vo.setAdvanceMonth(req.getAdvanceMonth());
        vo.setPrincipalAmount(req.getPrincipalAmount());
        vo.setRecoveredAmount(BigDecimal.ZERO);
        vo.setBalance(req.getPrincipalAmount());
        vo.setStatus("OUTSTANDING");
        vo.setMemo(req.getMemo());
        mapper.insert(vo);
        return vo.getAdvanceId();
    }

    /**
     * 선지급 면제 — status = WAIVED, balance = 0.
     */
    @Transactional
    public void waive(Long advanceId) {
        AdvancePaymentResp resp = mapper.selectById(advanceId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        if ("CLEARED".equals(resp.getStatus()) || "WAIVED".equals(resp.getStatus())) {
            throw new BizException(ErrorCode.INVALID_PARAMETER);
        }
        AdvancePaymentVO vo = new AdvancePaymentVO();
        vo.setAdvanceId(advanceId);
        vo.setAgentId(resp.getAgentId());
        vo.setAdvanceMonth(resp.getAdvanceMonth());
        vo.setPrincipalAmount(resp.getPrincipalAmount());
        vo.setRecoveredAmount(resp.getRecoveredAmount());
        vo.setBalance(BigDecimal.ZERO);
        vo.setStatus("WAIVED");
        vo.setMemo(resp.getMemo());
        mapper.update(vo);
    }

    /**
     * 설계사의 미상환 잔액 합계 (OUTSTANDING + PARTIAL).
     */
    public BigDecimal outstandingByAgent(Long agentId) {
        BigDecimal total = mapper.outstandingByAgent(agentId);
        return total != null ? total : BigDecimal.ZERO;
    }
}
