package cokr.xit.fims.levy.service.bean;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import cokr.xit.fims.crdn.Crdn;
import cokr.xit.fims.crdn.service.bean.CrdnStngBean;
import cokr.xit.fims.levy.Levy;
import cokr.xit.fims.levy.LevyQuery;
import cokr.xit.fims.levy.Rdct;
import cokr.xit.fims.levy.dao.LevyMapper;
import cokr.xit.fims.levy.dao.RdctMapper;
import cokr.xit.fims.mngt.service.bean.TaskProcessor;
import cokr.xit.foundation.component.AbstractBean;
import cokr.xit.foundation.data.DataObject;

/**과태료 감경 대장 정보 관리 Bean
 *
 * <p>상세 설명:
 *
 * <pre>
 * ============ 변경 이력 ============
 * 2023-08-30    JoJH 최초 작성
 * ================================
 * </pre>
 */
@Component("rdctBean")
public class RdctBean extends AbstractBean {
    /** 과태료 감경 대장 정보 DAO */
    @Resource(name = "rdctMapper")
    private RdctMapper rdctMapper;
    /** 부과 대장 정보 DAO */
    @Resource(name = "levyMapper")
    private LevyMapper levyMapper;
    @Resource(name = "crdnStngBean")
    private CrdnStngBean crdnStngBean;

    /**지정한 조건에 따라 과태료 감경 대장 목록을 조회하여 반환한다.
     * @param req 과태료 감경 대장 조회 조건
     * @return 과태료 감경 대장 목록
     */
    public List<DataObject> getRdctList(LevyQuery req) {
        if (req.getDelYn() == null) {
            req.setDelYn("N");
        }
        if (req.getOrderBy() == null) {
            req.setOrderBy("REG_DT");
        }

        return rdctMapper.selectRdctList(req);
    }

    /**지정한 조건에 따라 과태료 감경 대장 객체들을 반환한다.
     * @param req 과태료 감경 대장 조회 조건
     * @return 과태료 감경 대장 객체 목록
     */
    public List<DataObject> getRdcts(LevyQuery req) {
        if (req.getOrderBy() == null) {
            req.setOrderBy("R.RDCT_ID DESC");
        }

        return rdctMapper.selectRdcts(req);
    }

    /**지정한 감경 ID의 과태료 감경 대장 객체를 반환한다.<br />
     * @param req 과태료 감경 대장 조회 조건
     * @return 과태료 감경 대장 객체
     */
    public DataObject getRdctInfo(LevyQuery req) {
        return rdctMapper.selectRdctInfo(req);
    }

    /**지정한 단속 ID의 단속 정보를 반환한다.<br />
     * @param req 과태료 감경 대장 조회 조건
     * @return 단속 정보
     */
    public DataObject getCrdnInfo(LevyQuery req) {
        DataObject dataCrdn = rdctMapper.selectCrdn(req);

        if ("create".equals(req.getCallPurpose())) {
            dataCrdn.set("RDCT_YMD", dataCrdn.get("TODAY"));                    // 감경 일자
            dataCrdn.set("RDCT_AMT", dataCrdn.get("CALC_RDCT_AMT"));            // 감경 금액
        }

        return dataCrdn;
    }

    /**과태료 감경 대장 정보를 등록한다.
     * @param rdct 과태료 감경 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String createRdct(Rdct rdct) {
        // 단속 ID로 단속, 감경 정보 조회
        DataObject crdnRdctInfo = rdctMapper.selectCrdnInfo(rdct.getCrdnId());
        // 감경 ID가 있다면 이미 부과제외 자료가 존재하므로 종료..
        if (!isEmpty(crdnRdctInfo.string("RDCT_ID")))
            return "[F] 작업 중 이미 등록된 자료가 존재합니다.";
        // 단속 상태 코드(CRDN_STTS_CD) 확인하여 부과(51) 이후라면..
        if (toInt(crdnRdctInfo.get("CRDN_STTS_CD")) > 51)
            return "[F] 작업 중 오류가 발생하였습니다.<br>현재 자료의 단속 상태가 " + crdnRdctInfo.string("CRDN_STTS_NM") + " 상태 입니다.";
        // 부과 가산금(LEVY_ADAMT)이 있다면..
        if (toInt(crdnRdctInfo.get("LEVY_ADAMT")) > 0)
            return "[F] 작업 중 오류가 발생하였습니다.<br>부과 가산금이 존재합니다.";

        // 과태료 감경(TB_RDCT) 대장을 등록한다.
        int rtnNocs = rdctMapper.insertRdct(rdct);
        if (rtnNocs != 1)
            throw new RuntimeException("과태료 감경 대장 등록에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback

        // 과태료 금액
        int ffnlgAmt = toInt(crdnRdctInfo.get("FFNLG_CRDN_AMT")) - rdct.getRdctAmt();                // 과태료 단속 금액 - 감경 금액
        // 사전통지 금액
        int advntceAmt = ffnlgAmt - (ffnlgAmt * toInt(crdnRdctInfo.get("ADVNTCE_RDCRT")) / 100);    // 과태료 금액 - (과태료 금액 * 사전통지 감경 율 / 100)

        // 단속(TB_CRDN) 대장을 수정한다.
        Crdn crdn = new Crdn();
        crdn.setCrdnId(rdct.getCrdnId());                                        // 단속 ID
        crdn.setFfnlgRdcrt(crdnRdctInfo.string("WKSN_RDCRT"));                    // 과태료 감경 율
        crdn.setFfnlgAmt(ffnlgAmt);                                                // 과태료 금액
        crdn.setAdvntceAmt(advntceAmt);                                            // 사전통지 금액

        rtnNocs = rdctMapper.updateCrdnRdct(crdn);
        if (rtnNocs != 1)
            throw new RuntimeException("감경 등록 중 단속대장 금액 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback

        // 부과 ID가 존재한다면 부과(TB_LEVY) 대장을 수정한다.
        if (!isEmpty(crdnRdctInfo.string("LEVY_ID"))) {
            // 가산금이 존재하는 확인
            if (toInt(crdnRdctInfo.get("LEVY_ADAMT")) != 0 )
                throw new RuntimeException("감경 등록 중 부과 대장에 가산금이 발생하여 부과 대장 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback

            Levy levy = new Levy();
            levy.setLevyId(crdnRdctInfo.string("LEVY_ID"));                        // 부과 ID
            levy.setFfnlgAmt(ffnlgAmt);                                         // 과태료 금액

            DataObject params = crdnRdctInfo.clone().set("ffnlgAmt", ffnlgAmt).set("advntceAmt", advntceAmt);
            int levyPcptax = TaskProcessor.get().getLevyPcptax(params);
            levy.setLevyPcptax(levyPcptax);                                    // 부과 본세 = 과태료 금액

            int lastAmt = levy.getLevyPcptax() - toInt(crdnRdctInfo.get("RCVMT_PCPTAX")) - toInt(crdnRdctInfo.get("RDAMT_PCPTAX"));
            levy.setLastAmt(lastAmt);                                            // 합계 금액 = 부과 본세 - 수납 본세 - 감액 본세

            rtnNocs = levyMapper.updateLevyRdct(levy);
            if (rtnNocs != 1)
                throw new RuntimeException("감경 등록 중 부과대장 금액 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
        }

        return "[S] 작업이 정상 처리 되었습니다.";
    }

    /**과태료 감경 대장 정보를 수정한다.
     * @param rdct 과태료 감경 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String updateRdct(Rdct rdct) {
        // 과태료 감경(TB_RDCT) 대장을 수정한다.
        int rtnNocs = rdctMapper.updateRdct(rdct);
        if (rtnNocs != 1)
            throw new RuntimeException("과태료 감경 대장 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback

        return "[S] 작업이 정상 처리 되었습니다.";
    }

    /**과태료 감경 대장 정보를 삭제한다.
     * @param rdct 과태료 감경 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String removeRdct(Rdct rdct) {
        // 단속 ID로 단속, 감경 정보 조회
        LevyQuery req = new LevyQuery()
        	.setRdctId(rdct.getRdctId())
        	.setDelYn("N");
        DataObject crdnRdctInfo = rdctMapper.selectCrdn(req);

        // 감경 ID가 조회되지 않았다면 종료..
        if (isEmpty(crdnRdctInfo.string("RDCT_ID")))
            return "[F] 작업 중 자료가 존재하지 않습니다.";
        // 단속 상태 코드(CRDN_STTS_CD) 확인하여 부과(51) 이후라면..
        if (toInt(crdnRdctInfo.get("CRDN_STTS_CD")) > 51)
            return "[F] 작업 중 오류가 발생하였습니다.<br>현재 자료의 단속 상태가 " + crdnRdctInfo.string("CRDN_STTS_NM") + " 상태 입니다.";
        // 부과 가산금(LEVY_ADAMT)이 있다면..
        if (toInt(crdnRdctInfo.get("LEVY_ADAMT")) > 0)
            return "[F] 작업 중 오류가 발생하였습니다.<br>부과 가산금이 존재합니다.";

        // 감경(TB_RDCT) 대장을 삭제한다.
        int rtnNocs = rdctMapper.deleteRdct(rdct);
        if (rtnNocs != 1)
            throw new RuntimeException("감경 대장 삭제에 실패하였습니다.");

        // 과태료 금액
        int ffnlgAmt = toInt(crdnRdctInfo.get("FFNLG_CRDN_AMT"));                                        // 과태료 단속 금액 - 감경 금액
        int advntceAmt = ffnlgAmt - (ffnlgAmt * toInt(crdnRdctInfo.get("ADVNTCE_RDCRT")) / 100);         // 과태료 금액 - (과태료 금액 * 사전통지 감경 율 / 100)

        // 단속(TB_CRDN) 대장을 수정한다.
        Crdn crdn = new Crdn();
        crdn.setCrdnId(crdnRdctInfo.string("CRDN_ID"));                         // 단속 ID
        crdn.setFfnlgRdcrt("0");                                                // 과태료 감경 율
        crdn.setFfnlgAmt(ffnlgAmt);                                             // 과태료 금액
        crdn.setAdvntceAmt(advntceAmt);                                         // 사전통지 금액

        rtnNocs = rdctMapper.updateCrdnRdct(crdn);
        if (rtnNocs != 1)
            throw new RuntimeException("감경 취소 중 단속대장 금액 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback

        // 부과 ID가 존재한다면 부과(TB_LEVY) 대장을 수정한다.
        String levyID = crdnRdctInfo.string("LEVY_ID");
		if (!isEmpty(levyID)) {
            // 가산금이 존재하는 확인
            if (toInt(crdnRdctInfo.get("LEVY_ADAMT")) != 0 )
                throw new RuntimeException("감경 취소 중 부과 대장에 가산금이 발생하여 부과 대장 수정에 실패하였습니다.");  // 예외를 발생시켜서 DB Rollback

            Levy levy = new Levy();
            levy.setLevyId(levyID);                     // 부과 ID
            levy.setFfnlgAmt(ffnlgAmt);                                         // 과태료 금액

            DataObject params = crdnRdctInfo.clone().set("ffnlgAmt", ffnlgAmt).set("advntceAmt", advntceAmt);
            int levyPcptax = TaskProcessor.get().getLevyPcptax(params);
            levy.setLevyPcptax(levyPcptax);                                    // 부과 본세 = 과태료 금액

            int lastAmt = levy.getLevyPcptax() + toInt(crdnRdctInfo.get("LEVY_ADAMT"))
                        - toInt(crdnRdctInfo.get("RCVMT_PCPTAX")) - toInt(crdnRdctInfo.get("RCVMT_ADAMT"))
                        - toInt(crdnRdctInfo.get("RDAMT_PCPTAX")) - toInt(crdnRdctInfo.get("RDAMT_ADAMT"));
            levy.setLastAmt(lastAmt);                                           // 합계 금액 = 부과 본세 + 부과 가산금 + 분납 이자 - 수납 본세 - 수납 가산금 - 감액 본세 - 감액 가산금

            rtnNocs = levyMapper.updateLevyRdct(levy);
            if (rtnNocs != 1)
                throw new RuntimeException("감경 등록 중 부과대장 금액 수정에 실패하였습니다.");     // 예외를 발생시켜서 DB Rollback
        }

        return "[S] 작업이 정상 처리 되었습니다.";
    }
}