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

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import cokr.xit.base.file.FileInfo;
import cokr.xit.base.file.service.FileQuery;
import cokr.xit.base.file.service.bean.FileBean;
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.LevyExclQuery;
import cokr.xit.fims.excl.OpnnSbmsn;
import cokr.xit.fims.excl.dao.OpnnSbmsnMapper;
import cokr.xit.fims.levy.LevyQuery;
import cokr.xit.fims.levy.Rdct;
import cokr.xit.fims.levy.service.bean.RdctBean;
import cokr.xit.foundation.component.AbstractBean;
import cokr.xit.foundation.data.DataObject;

/**의견제출 대장 정보 관리 Bean
 *
 * <p>상세 설명: 의견제출 대장 DAO(OpnnSbmsnMapper)를 사용해 업무 기능을 구현한 클래스
 *
 * <pre>
 * ============ 변경 이력 ============
 * 2023-06-27    JoJH 최초 작성
 * ================================
 * </pre>
 */
@Component("opnnSbmsnBean")
public class OpnnSbmsnBean extends AbstractBean {

    /** 의견제출 대장 정보 DAO */
    @Resource(name="opnnSbmsnMapper")
    private OpnnSbmsnMapper opnnSbmsnMapper;

    /** 첨부파일 Bean */
    @Resource(name="fileBean")
    private FileBean fileBean;

    /** 단속 상태 이력 정보 Bean */
    @Resource(name="crdnSttsHstryBean")
    private CrdnSttsHstryBean crdnSttsHstryBean;

    /** 과태료 감경 대장 정보 Bean */
    @Resource(name="rdctBean")
    private RdctBean rdctBean;

    /**지정한 조건에 따라 의견제출 대장 목록을 조회하여 반환한다.
     * @param req 의견제출 대장 조회 조건
     * @return 의견제출 대장 목록
     */
    public List<DataObject> getOpnnSbmsnList(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 opnnSbmsnMapper.selectOpnnSbmsnList(req);
    }

    /**지정한 조건에 따라 의견제출 대장 객체들을 반환한다.
     * @param req 의견제출 대장 조회 조건
     * @return 의견제출 대장 객체 목록
     */
    public List<DataObject> getOpnnSbmsns(LevyExclQuery req) {
        // 삭제 여부 확인
        if (req.getDelYn() == null) {
            req.setDelYn("N");
        }
        // 정렬 확인
        if (req.getOrderBy() == null) {
            req.setOrderBy("OS.OPNN_ID DESC");
        }

        return opnnSbmsnMapper.selectOpnnSbmsns(req);
    }

    /**지정한 조건에 따라 의견제출 정보를 반환한다.
     * @param req 의견제출 대장 조회 조건
     * @return 의견제출 정보
     */
    public DataObject getOpnnSbmsnInfo(LevyExclQuery req) {
        return opnnSbmsnMapper.selectOpnnSbmsnInfo(req);
    }

    /**지정한 조건에 따라 의견제출 심의 의결서 객체들을 반환한다.
     * @param req 의견제출 대장 조회 조건
     * @return 의견제출 대장 객체 목록
     */
    public List<DataObject> getOpnnSbmsnDlbrDecsns(LevyExclQuery req) {
        // 정렬 확인
        if (req.getOrderBy() == null) {
            req.setOrderBy("OS.OPNN_ID DESC");
        }

        return opnnSbmsnMapper.selectOpnnSbmsnDlbrDecsns(req);
    }

    /**의견제출 대장 정보를 등록한다.
     * @param opnnSbmsn 의견제출 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String createOpnnSbmsn(OpnnSbmsn opnnSbmsn, List<FileInfo> fileInfoList) {
        // 변수 선언
        boolean rtnScs = false;
        int rtnNocs = -1;														// 처리 결과 건수
        String rtnMsg = "";														// 처리 결과 메시지

        // 단속 ID로 단속, 의견제출 정보 조회
        LevyExclQuery req = new LevyExclQuery();
        req.setCrdnId(opnnSbmsn.getCrdnId());
        req.setDelYn("N");
        DataObject crdnOpnnSbmsnInfo = opnnSbmsnMapper.selectOpnnSbmsnInfo(req);

        // 의견제출 ID가 있다면 이미 자료가 존재하므로 종료..
        if (!crdnOpnnSbmsnInfo.string("OPNN_ID").equals("")) {
            rtnMsg = "[F] 작업 중 이미 등록된 의견제출 자료가 존재합니다.";
        }
        // 단속 상태 코드가 부과(51) 보다 크다면, 의견제출 등록을 할 수 없다. 종료..
        if (toInt(crdnOpnnSbmsnInfo.get("CRDN_STTS_CD")) >= 51) {
            rtnMsg = "[F] 작업 중 오류가 발생하였습니다."
                    + "<br>현재 자료의 단속 상태가 " + crdnOpnnSbmsnInfo.string("CRDN_STTS_NM") + " 상태 입니다.";
        }
        // 오류메세지가 발생하면 종료..
        if (rtnMsg.contains("[F]")) {
            return rtnMsg;
        }

        // 의견제출(TB_OPNN_SBMSN) 대장을 등록한다.
        rtnNocs = opnnSbmsnMapper.insertOpnnSbmsn(opnnSbmsn);                   // 의견제출 등록
        if (rtnNocs != 1) {
            throw new RuntimeException("의견제출 대장 등록에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
        }

        // 의견제출 파일 첨부하기
        if (fileInfoList != null && !fileInfoList.isEmpty()) {
            fileInfoList.forEach(fileInfo -> fileInfo.setInfoType(OpnnSbmsn.INF_TYPE).setInfoKey(opnnSbmsn.getOpnnId()));

            fileBean.create(fileInfoList);
        }

        // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장 등록 및 단속 대장의 단속 상태 코드를 수정한다.
        CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();
        crdnSttsHstry.setCrdnId(crdnOpnnSbmsnInfo.string("CRDN_ID"));
        crdnSttsHstry.setBfrSttsCd(crdnOpnnSbmsnInfo.string("CRDN_STTS_CD"));
        crdnSttsHstry.setBfrSttsChgDt(crdnOpnnSbmsnInfo.string("CRDN_STTS_CHG_DT"));
        crdnSttsHstry.setCrdnSttsCd("31");                                      // 의견제출 접수
        crdnSttsHstry.setTaskDtlId(opnnSbmsn.getOpnnId());

        // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장에 등록한다.
        rtnScs = crdnSttsHstryBean.createHstryUpdateCrdnSttsCd(crdnSttsHstry);
        if (!rtnScs) {
            throw new RuntimeException("의견제출 등록 중 단속대장의 단속상태 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
        }

        // 단속 대장(TB_CRDN) 의견제출여부(OPNN_SBMSN_YN) 정보를 수정한다.
        Crdn crdn = new Crdn();
        crdn.setCrdnId(crdnOpnnSbmsnInfo.string("CRDN_ID"));
        crdn.setOpnnSbmsnYn("Y");

        rtnNocs = opnnSbmsnMapper.updateCrdnOpnnSbmsnYn(crdn);                    // 단속 대장 수정
        if (rtnNocs != 1) {
            throw new RuntimeException("의견제출 등록 중 단속 대장의 의견제출여부 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
        }

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

    /**의견제출 대장 정보를 수정한다.
     * @param opnnSbmsn 의견제출 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String updateOpnnSbmsn(OpnnSbmsn opnnSbmsn, List<FileInfo> fileInfoList) {
        // 의견제출 첨부파일 등록
        if (fileInfoList != null && !fileInfoList.isEmpty()) {
            fileInfoList.forEach(fileInfo -> fileInfo.setInfoType(OpnnSbmsn.INF_TYPE)
                                                        .setInfoKey(opnnSbmsn.getOpnnId()));

            fileBean.create(fileInfoList);                                        // 파일 등록

            // 의견제출 ID로 파일(TB_FILE) 정보 조회
            List<DataObject> infoFileList = fileBean.getFileList(new FileQuery().setInfoType(OpnnSbmsn.INF_TYPE)
                                                                                .setInfoKeys(opnnSbmsn.getOpnnId())
                                                                                .setOrderBy("FILE_ID"));

            if (infoFileList != null && infoFileList.size() > 0) {
                String[] fileIDs = new String[infoFileList.size()];

                for (int iLoop = 0; iLoop < infoFileList.size(); iLoop++) {
                    fileIDs[iLoop] = infoFileList.get(iLoop).string("FILE_ID");
                }

                fileBean.reorder(fileIDs);                                        // 첨부파일 재 정렬
            }
        }

        // 의견제출 대장을 수정한다.
        int rtnNocs = opnnSbmsnMapper.updateOpnnSbmsn(opnnSbmsn);
        if (rtnNocs != 1) {
            throw new RuntimeException("의견제출 대장 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
        }

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

    /**의견제출 대장 심의(답변) 정보를 수정한다.
     * @param opnnSbmsn 의견제출 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String updateOpnnSbmsnAnswer(OpnnSbmsn opnnSbmsn) {
        // 변수 선언
        boolean rtnScs = false;
        int rtnNocs = -1;                                                       // 처리 결과 건수
        String rtnMsg = "";                                                     // 처리 결과 메시지

        // 의견제출(TB_OPNN_SBMSN) 자료 조회
        LevyExclQuery req = new LevyExclQuery();
        req.setOpnnId(opnnSbmsn.getOpnnId());
        req.setDelYn("N");
        DataObject opnnSbmsnInfo = opnnSbmsnMapper.selectOpnnSbmsnInfo(req);

        // 과태료 감경 대장(TB_RDCT) 자료 조회
        LevyQuery reqLevy = new LevyQuery();
        reqLevy.setCrdnId(opnnSbmsn.getCrdnId());
        reqLevy.setDelYn("N");
        DataObject rdctInfo = rdctBean.getRdctInfo(reqLevy);

        // 의견제출 ID가 조회되지 않았다면 종료..
        if (opnnSbmsnInfo.string("OPNN_ID").equals("")) {
            rtnMsg = "[F] 작업 중 오류가 발생하였습니다."
                    + "<br>의견제출 자료가 존재하지 않습니다.";
        }
        // 과태료 감경 대장에 이미 감경이 등록 되었다면 의견제출 과태료감경(04)을 처리할 수 없다.
        if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("04") && !rdctInfo.string("RDCT_ID").equals("")) {
            rtnMsg = "[F] 작업 중 오류가 발생하였습니다."
                    + "<br>현재 자료는 과태료 감경이 이미 등록 되었습니다.";
        }
        // 오류메세지가 발생하면 종료..
        if (rtnMsg.contains("[F]")) {
            return rtnMsg;
        }

        // 의견제출 답변을 수정한다.
        rtnNocs = opnnSbmsnMapper.updateOpnnSbmsnAnswer(opnnSbmsn);
        if (rtnNocs != 1) {
            throw new RuntimeException("의견제출 심의 처리에 실패하였습니다."); // 예외를 발생시켜서 DB Rollback
        }

        // 현재 의견제출상태 코드와 변경 할 의견제출상태 코드가 다르다면..
        if (!opnnSbmsn.getOpnnSbmsnSttsCd().equals(opnnSbmsnInfo.string("OPNN_SBMSN_STTS_CD"))) {
            // 의견제출답변결과(OPNN_SBMSN_STTS_CD)가 과태료감경(04) 이라면 감경 등록
            if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("04")) {
                Rdct rdct = new Rdct();
                rdct.setSggCd(opnnSbmsnInfo.string("SGG_CD"));
                rdct.setCrdnId(opnnSbmsnInfo.string("CRDN_ID"));
                rdct.setRtpyrId(opnnSbmsnInfo.string("RTPYR_ID"));
                rdct.setRdctYmd(opnnSbmsn.getAnsYmd());
                rdct.setRdctRsnCd(opnnSbmsn.getRdctRsnCd());
                rdct.setRdctAmt(opnnSbmsn.getRdctAmt());
                rdct.setEtcCn("의견제출 심의 처리에 의한 감경 등록");

                rtnMsg = rdctBean.createRdct(rdct);
                if (!rtnMsg.contains("[S]")) {
                    throw new RuntimeException("의견제출 심의 처리 중 과태료 감경 등록에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
                }
            } else {
                if (!rdctInfo.string("RDCT_ID").equals("") && (rdctInfo.string("ETC_CN").contains("의견제출"))) {
                    Rdct rdct = new Rdct();
                    rdct.setRdctId(rdctInfo.string("RDCT_ID"));
                    rdct.setDelRsn("의견제출 심의 처리에 의한 감경 삭제");

                    rtnMsg = rdctBean.removeRdct(rdct);
                    if (!rtnMsg.contains("[S]")) {
                        throw new RuntimeException("의견제출 심의 처리 중 과태료 감경 등록(수정)에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
                    }
                }
            }

            // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장에 등록한다.
            CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();

            // 심의결과를 접수로 처리할 때 이전 단속상태코드를 확인하여 이전 단속상태코드로 변경한다.
            if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("00")) {
                if (opnnSbmsnInfo.string("OPNN_SBMSN_STTS_CD").equals("02")) {
                    crdnSttsHstry.setCrdnSttsCd("82");
                } else if (opnnSbmsnInfo.string("OPNN_SBMSN_STTS_CD").equals("06")) {
                    crdnSttsHstry.setCrdnSttsCd("87");
                } else {
                    crdnSttsHstry.setCrdnSttsCd("31");
                }

                crdnSttsHstry.setCrdnId(opnnSbmsnInfo.string("CRDN_ID"));
                crdnSttsHstry.setEtcCn("의견제출 심의 처리로 인한 단속 상태 변경");

                if ("82,87".contains(opnnSbmsnInfo.string("CRDN_STTS_CD"))) {
                    // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장의 사용 여부를 "N"으로 처리하고, 단속(TB_CRDN) 대장의 단속 상태 코드를 수정한다.
                    rtnScs = crdnSttsHstryBean.removeHstryUpdateCrdnSttsCd(crdnSttsHstry);
                    if (!rtnScs) {
                        throw new RuntimeException("의견제출 심의(답변) 작업중 단속 대장의 단속상태 삭제에 실패하였습니다."); // 예외를 발생시켜서 DB Rollback
                    }
                } else if (!opnnSbmsnInfo.string("CRDN_STTS_CD").equals("31") && toInt(opnnSbmsnInfo.get("CRDN_STTS_CD")) < 50) {
                    crdnSttsHstry.setBfrSttsCd(opnnSbmsnInfo.string("CRDN_STTS_CD"));
                    crdnSttsHstry.setBfrSttsChgDt(opnnSbmsnInfo.string("CRDN_STTS_CHG_DT"));
                    crdnSttsHstry.setTaskDtlId(opnnSbmsn.getOpnnId());
                    crdnSttsHstry.setUseYn("Y");

                    rtnScs = crdnSttsHstryBean.createHstryUpdateCrdnSttsCd(crdnSttsHstry);
                    if (!rtnScs) {
                        throw new RuntimeException("의견제출 심의(답변) 작업중 단속 대장의 단속상태 변경에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
                    }
                }
            } else {
                String newCrdnSttsCd = "";

                if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("02")) {
                    newCrdnSttsCd = "82";                                           // 의견제출 수용
                } else if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("06")) {
                    newCrdnSttsCd = "87";                                           // 경찰서 이첩
                } else if ("01,03,04,05".contains(opnnSbmsn.getOpnnSbmsnSttsCd())) {
                    // 현재 단속 상태 코드가 의견제출 접수라면 이전 단속 상태 코드로 등록한다.
                    if (opnnSbmsnInfo.string("CRDN_STTS_CD").equals("31")) {
                        // 단속 상태 이력(TB_CRDN_STTS_HSTRY) 자료 조회
                        DataObject infoCrdnSttsHstry = crdnSttsHstryBean.getCrdnSttsHstryInfo(opnnSbmsnInfo.string("CRDN_ID"), "31", "Y");
                        newCrdnSttsCd = infoCrdnSttsHstry.string("BFR_STTS_CD");    // 이전 단속상태코드 유지
                    } else {
                        newCrdnSttsCd = "";
                    }
                } else {
                    throw new RuntimeException("의견제출 심의 처리중 지정되지 않은 심의 상태가 입력되었습니다.");    // 예외를 발생시켜서 DB Rollback
                }

                if (!newCrdnSttsCd.equals("")) {
                    crdnSttsHstry.setCrdnId(opnnSbmsnInfo.string("CRDN_ID"));
                    crdnSttsHstry.setBfrSttsCd(opnnSbmsnInfo.string("CRDN_STTS_CD"));
                    crdnSttsHstry.setBfrSttsChgDt(opnnSbmsnInfo.string("CRDN_STTS_CHG_DT"));
                    crdnSttsHstry.setCrdnSttsCd(newCrdnSttsCd);
                    crdnSttsHstry.setTaskDtlId(opnnSbmsn.getOpnnId());
                    crdnSttsHstry.setEtcCn("의견제출 심의 처리로 인한 단속 상태 변경");
                    crdnSttsHstry.setUseYn("Y");

                    rtnScs = crdnSttsHstryBean.createHstryUpdateCrdnSttsCd(crdnSttsHstry);
                    if (!rtnScs) {
                        throw new RuntimeException("의견제출 심의(답변) 처리 중 단속대장의 단속상태 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
                    }
                }
            }
        }

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

    /**의견제출 대장 정보를 삭제한다.
     * @param opnnSbmsn 의견제출 대장
     * @return 저장 여부
     * <ul><li>저장됐으면 true</li>
     *     <li>그렇지 않으면 false</li>
     * </ul>
     */
    public String removeOpnnSbmsn(OpnnSbmsn opnnSbmsn) {
        // 변수 선언
        boolean rtnScs = false;
        int rtnNocs = -1;                                                       // 처리 결과 건수
        String rtnMsg = "";                                                     // 처리 결과 메시지

        // 의견제출(TB_OPNN_SBMSN) 정보를 조회한다.
        LevyExclQuery req = new LevyExclQuery();
        req.setOpnnId(opnnSbmsn.getOpnnId());
        req.setDelYn("N");
        DataObject opnnSbmsnInfo = opnnSbmsnMapper.selectOpnnSbmsnInfo(req);

        // 의견제출 ID가 조회되지 않았다면 종료..
        if (opnnSbmsnInfo.string("OPNN_ID").equals("")) {
            rtnMsg = "[F] 작업 중 오류가 발생하였습니다.<br>의견제출 자료가 존재하지 않습니다.";
            return rtnMsg;
        }
        // 의견제출 상태 코드(OPNN_SBMSN_STTS_CD) 확인..
        if (!"00,03".contains(opnnSbmsnInfo.string("OPNN_SBMSN_STTS_CD"))) {
            rtnMsg = "[F] 작업 중 오류가 발생하였습니다.<br>현재 자료의 의견제출 상태가 " + opnnSbmsnInfo.string("OPNN_SBMSN_STTS_NM") + " 입니다.";
            return rtnMsg;
        }

        // 의견제출(TB_OPNN_SBMSN) 대장을 삭제한다.
        rtnNocs = opnnSbmsnMapper.deleteOpnnSbmsn(opnnSbmsn);
        if (rtnNocs != 1) {
            throw new RuntimeException("의견제출 대장 삭제에 실패하였습니다."); // 예외를 발생시켜서 DB Rollback
        }

        // 첨부파일 삭제
        String[] deleteFiles = {opnnSbmsn.getOpnnId()};
        fileBean.remove(OpnnSbmsn.INF_TYPE, deleteFiles);

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

        if (opnnSbmsnInfo.string("CRDN_STTS_CD").equals("31")) {
            rtnScs = crdnSttsHstryBean.removeHstryUpdateCrdnSttsCd(crdnSttsHstry);
            if (!rtnScs) {
                throw new RuntimeException("의견제출 삭제 작업중 단속 대장의 단속상태 변경에 실패하였습니다."); // 예외를 발생시켜서 DB Rollback
            }
        } else {
            rtnScs = crdnSttsHstryBean.remove(crdnSttsHstry);
            if (!rtnScs) {
                throw new RuntimeException("의견제출 삭제 작업중 단속상태 이력 삭제에 실패하였습니다."); // 예외를 발생시켜서 DB Rollback
            }
        }

        // 단속 대장(TB_CRDN) 의견제출여부(OPNN_SBMSN_YN) 정보를 수정한다.
        Crdn crdn = new Crdn();
        crdn.setCrdnId(opnnSbmsnInfo.string("CRDN_ID"));
        crdn.setOpnnSbmsnYn("N");

        // 단속(TB_CRDN) 대장을 수정한다.
        rtnNocs = opnnSbmsnMapper.updateCrdnOpnnSbmsnYn(crdn);
        if (rtnNocs != 1) {
            throw new RuntimeException("의견제출 삭제 중 단속대장의 의견제출여부 수정에 실패하였습니다.");    // 예외를 발생시켜서 DB Rollback
        }

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

}
