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

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import cokr.xit.fims.cmmn.CmmnUtil;
import cokr.xit.fims.cmmn.CrdnSttsHstry;
import cokr.xit.fims.cmmn.service.bean.CrdnSttsHstryBean;
import cokr.xit.fims.crdn.Crdn;
import cokr.xit.fims.excl.LevyExcl;
import cokr.xit.fims.excl.LevyExclQuery;
import cokr.xit.fims.excl.dao.LevyExclMapper;
import cokr.xit.fims.rdca.Rdamt;
import cokr.xit.fims.rdca.service.bean.RdamtBean;
import cokr.xit.foundation.component.AbstractBean;
import cokr.xit.foundation.data.DataObject;

/**부과제외 대장 정보 관리 Bean
 *
 * <p>상세 설명: 부과제외 대장 DAO(Excl01Mapper)를 사용해 업무 기능을 구현한 클래스
 *
 * <pre>
 * ============ 변경 이력 ============
 * 2023-06-23    JoJH 최초 작성
 * ================================
 * </pre>
 */
@Component("levyExclBean")
public class LevyExclBean extends AbstractBean {
    /** 부과제외 대장 정보 DAO */
    @Resource(name="levyExclMapper")
    private LevyExclMapper levyExclMapper;
    /** 단속 상태 이력 정보 Bean */
    @Resource(name="crdnSttsHstryBean")
    private CrdnSttsHstryBean crdnSttsHstryBean;
    /** 감액 대장 정보 Bean */
    @Resource(name="rdamtBean")
    private RdamtBean rdamtBean;

    /**지정한 조건에 따라 부과제외 대장 목록을 조회하여 반환한다.
     * @param req 부과제외 조회 조건
     * @return 부과제외 대장 목록
     */
    public List<DataObject> getLevyExclList(LevyExclQuery req) {
        // 삭제 여부 확인
        if (req.getDelYn() == null) {
            req.setDelYn("N");
        }
        // 정렬 확인
        if (req.getOrderBy() == null) {
            if (req.getBy() == null) {
                req.setOrderBy("REG_DT");
            } else {
                req.setOrderBy(CmmnUtil.convertCamelCaseToSnakeCase(req.getBy()));
            }
        }

        return levyExclMapper.selectLevyExclList(req);
    }

    /**지정한 조건에 따라 부과제외 이력 객체들을 반환한다.
     * @param req 부과제외 조회 조건
     * @return 부과제외 객체 목록
     */
    public List<DataObject> getLevyExcls(LevyExclQuery req) {
        // 삭제 여부 확인
        if (req.getDelYn() == null) {
            req.setDelYn("N");
        }
        // 정렬 확인
        if (req.getOrderBy() == null) {
            req.setOrderBy("LE.LEVY_EXCL_ID DESC");
        }

        return levyExclMapper.selectLevyExcls(req);
    }

    /**지정한 부과제외 ID의 부과제외 정보를 반환한다.
     * @param req 부과제외 조회 조건
     * @return 부과제외 정보
     */
    public DataObject getLevyExclInfo(LevyExclQuery req) {
        DataObject info = levyExclMapper.selectLevyExclInfo(req);

        // 신규 부과제외 등록일 경우 부과제외 구분코드를 입력한다.
        if ("create".equals(req.getCallPurpose()))
            info.set("LEVY_EXCL_SE_CD", req.getLevyExclSeCd())
            	.set("LEVY_EXCL_SE_NM", info.string("CRT_LEVY_EXCL_SE_NM"));

        return info;
    }

    /**부과제외 대장 정보를 등록한다.
     * @param excl 부과제외 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String createLevyExcl(LevyExcl levyExcl) {
        // 단속 ID로 단속, 부과제외 정보 조회
        LevyExclQuery req = new LevyExclQuery();
        req.setCrdnId(levyExcl.getCrdnId());
        req.setDelYn("N");
        DataObject levyExclInfo = levyExclMapper.selectLevyExclInfo(req);

        // 등록 대상 자료 검증
        if (!isEmpty(levyExclInfo.string("LEVY_EXCL_ID")))                  // 부과제외 ID가 있다면 이미 부과제외 자료가 존재하므로 종료..
            return "[F] 이미 등록된 부과제외 자료가 존재합니다.";
        if (!isEmpty(levyExclInfo.string("CVLCPT_LINK_ID"))) {                // 민원 ID
            if (levyExclInfo.string("CVLCPT_PRCS_CD").equals("00"))           // 민원 처리상태 확인
                return "[F] 단속 민원 자료가 처리 되지 않았습니다."
                       + "<br>단속 민원 업무를 먼저 처리 하시기 바랍니다.";
        }

        int crdnSttsCd = toInt(levyExclInfo.get("CRDN_STTS_CD"));
		String levyExclSeCd = levyExcl.getLevyExclSeCd();
		if ("1,2".contains(levyExclSeCd)) {                       // 부과제외(서손), 계고
            if (crdnSttsCd >= 51)         // 단속상태코드가 부과(51) 보다 크다면, 부과제외 또는 계고 등록을 할 수 없다.
                return "[F] 작업 중 오류가 발생하였습니다."
                       + "<br>단속 자료의 처리상태가 " + levyExclInfo.string("CRDN_STTS_NM") + " 입니다";
        } else if ("3".equals(levyExclSeCd)) {                    // 부과취소
            if (crdnSttsCd < 51)          // 단속상태코드가 부과(51) 보다 작다면, 전액감액 등록 할 수 없다.
                return "[F] 작업 중 오류가 발생하였습니다."
                       + "<br>단속 자료의 처리상태가 " + levyExclInfo.string("CRDN_STTS_NM") + " 입니다";
            if (crdnSttsCd > 55)          // 단속상태코드가 압류(55) 보다 크면, 전액감액 등록 할 수 없다.
                return "[F] 작업 중 오류가 발생하였습니다."
                       + "<br>단속 자료의 처리상태가 " + levyExclInfo.string("CRDN_STTS_NM") + " 입니다";
            if (levyExclInfo.string("LEVY_ID").isEmpty())                    // 부과(TB_LEVY) 정보 확인
                return "[F] 작업 중 오류가 발생하였습니다."
                       + "<br>부과 자료가 존재하지 않습니다."
                       + "<br>부과제외로 처리하시기 바랍니다.";
        }

        // 표지정보 확인여부가 미확인(0)이면 -> 조회미대상(9) 으로
        if (levyExclInfo.string("PRK_PSBLTY_RSLT_CD").equals("0")) {            // 주차 가능 결과 코드(FIM034) 0: 미확인
            Crdn crdn = new Crdn();
            crdn.setCrdnId(levyExclInfo.string("CRDN_ID"));                     // 단속 ID
            crdn.setPrkPsbltyRsltCd("9");                                       // 주차 가능 결과 코드(FIM034) 9: 조회미대상

            if (levyExclMapper.updatePrkPsbltyRsltCd(crdn) != 1)
                throw new RuntimeException("부과제외 등록 중 단속 대장의 표지정보 수정에 실패하였습니다.");
        }

        // 부과취소(전액감액)일 경우 부과(TB_LEVY)에 감액금액 입력이 필요..
        if (levyExclSeCd.equals("3")) {
            // 감액(TB_RDAMT) 등록
            Rdamt rdamt = new Rdamt();
            rdamt.setSggCd(levyExclInfo.string("SGG_CD"));
            rdamt.setLevyId(levyExclInfo.string("LEVY_ID"));                    // 부과 ID
            rdamt.setRdamtYmd(levyExcl.getLevyExclYmd());                       // 감액 일자
            rdamt.setRdamtSeCd("02");                                           // 감액 구분 코드 FIM085 - 02:부과취소
            rdamt.setRdamtRsnCd(levyExcl.getLevyExclRsnCd());                   // 감액 사유 코드

            String rtnMsg = rdamtBean.createRdamt(rdamt);
            if (!rtnMsg.contains("[S]"))
                throw new RuntimeException(rtnMsg.replace("[F]", ""));

            levyExcl.setRdamtId(rdamt.getRdamtId());                            // 감액 ID
        }

        // 부과제외(TB_LEVY_EXCL) 대장을 등록한다.
        if (levyExclMapper.insertLevyExcl(levyExcl) != 1)
            throw new RuntimeException("부과제외 정보 등록에 실패하였습니다.");

        // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장에 등록하고, 단속(TB_CRDN) 대장을 수정한다.
        // 단속 상태 이력(TB_CRDN_STTS_HSTRY)
        CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();
        crdnSttsHstry.setCrdnId(levyExclInfo.string("CRDN_ID"));
        crdnSttsHstry.setBfrSttsCd(levyExclInfo.string("CRDN_STTS_CD"));
        crdnSttsHstry.setBfrSttsChgDt(levyExclInfo.string("CRDN_STTS_CHG_DT"));
        crdnSttsHstry.setCrdnSttsCd(switch (levyExclSeCd) {
        case "1" -> "81"; // 부과제외 -> 부과제외(서손)
        case "2" -> "83"; // 계고 -> 계고
        case "3" -> "80"; // 부과취소(전액감액) -> 부과취소
        default -> "";
        });
        crdnSttsHstry.setTaskDtlId(levyExcl.getLevyExclId());

        if (!crdnSttsHstryBean.createHstryUpdateCrdnSttsCd(crdnSttsHstry))
            throw new RuntimeException("부과제외 등록 중 단속상태 변경에 실패하였습니다.");

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

    /**부과제외 대장 정보를 수정한다.
     * @param excl 부과제외 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String updateLevyExcl(LevyExcl levyExcl) {
        // 부과제외(TB_LEVY_EXCL) 대장을 수정한다.
        if (levyExclMapper.updateLevyExcl(levyExcl) != 1)
            throw new RuntimeException("부과제외 정보 수정에 실패하였습니다.");

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

    /**부과제외 대장 정보를 삭제한다.
     * @param excl 부과제외 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String removeLevyExcl(LevyExcl levyExcl) {
        // 부과제외(TB_LEVY_EXCL) 정보를 조회한다.
        LevyExclQuery req = new LevyExclQuery();
        req.setLevyExclId(levyExcl.getLevyExclId());
        req.setDelYn("N");
        DataObject levyExclInfo = levyExclMapper.selectLevyExclInfo(req);

        // 삭제 대상 자료 검증
        if (levyExclInfo == null)
            return "[F] 부과제외 자료가 조회되지 않습니다.";

        String levyExclSeCd = levyExclInfo.string("LEVY_EXCL_SE_CD");
		String crdnSttsCd = levyExclInfo.string("CRDN_STTS_CD");
		if (levyExclSeCd.equals("1") && !crdnSttsCd.equals("81")) {              // 부과제외(서손)
            return "[F] 단속 처리상태가 " + levyExclInfo.string("CRDN_STTS_NM") + " 입니다.";
        } else if (levyExclSeCd.equals("2") && !("83").contains(crdnSttsCd)) {   // 계고
            return "[F] 단속 자료의 처리상태가 " + levyExclInfo.string("CRDN_STTS_NM") + " 입니다.";
        } else if (levyExclSeCd.equals("3") && !crdnSttsCd.equals("80")) {       // 부과취소
            return "[F] 단속 자료의 처리상태가 " + levyExclInfo.string("CRDN_STTS_NM") + " 입니다.";
        }

        int rtnNocs = -1;                                                       // 처리 결과 건수
        // 부과제외 구분이 부과제외(서손)일 경우
        String crdnId = levyExclInfo.string("CRDN_ID");
		if ("1".equals(levyExclSeCd)) {
            // 표지정보 확인여부가 조회미대상이면 -> 미확인 으로
            if ("9".equals(levyExclInfo.get("PRK_PSBLTY_RSLT_CD"))) {        // 주차 가능 결과 코드 - 9 조회 미대상
                Crdn crdn = new Crdn();
                crdn.setCrdnId(crdnId);                 // 단속 ID
                crdn.setPrkPsbltyRsltCd("0");                                   // 주차 가능 결과 코드 - 0 미확인

                rtnNocs = levyExclMapper.updatePrkPsbltyRsltCd(crdn);
                if (rtnNocs != 1)
                    throw new RuntimeException("부과제외 삭제 중 단속 대장의 표지정보 수정에 실패하였습니다.");
            }
        }

        // 부과제외(TB_LEVY_EXCL) 대장을 삭제한다.
        rtnNocs = levyExclMapper.deleteLevyExcl(levyExcl);
        if (rtnNocs != 1)
            throw new RuntimeException("부과제외 정보 삭제에 실패하였습니다.");

        // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장의 사용 여부를 "N"으로 처리하고, 단속(TB_CRDN) 대장의 단속 상태 코드를 수정한다.
        CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();
        crdnSttsHstry.setCrdnId(crdnId);                // 단속 ID
        crdnSttsHstry.setCrdnSttsCd(crdnSttsCd);       // 단속 상태 코드
        crdnSttsHstry.setEtcCn(levyExcl.getDelRsn());                           // 기타 내용 - 삭제 사유
        crdnSttsHstry.setUseYn("N");                                            // 사용 여부

        if (!crdnSttsHstryBean.removeHstryUpdateCrdnSttsCd(crdnSttsHstry))
            throw new RuntimeException("부과제외 삭제 중 단속 대장의 단속상태 변경에 실패하였습니다.");

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