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

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import cokr.xit.fims.excl.OpnnSbmsn;
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.CrdnSttsHstry;
import cokr.xit.fims.cmmn.service.bean.CrdnSttsHstryBean;
import cokr.xit.fims.crdn.Crdn;
import cokr.xit.fims.excl.ExclQuery;
import cokr.xit.fims.excl.dao.OpnnSbmsnMapper;
import cokr.xit.fims.levy.Rduct;
import cokr.xit.fims.levy.service.bean.Levy02Bean;
import cokr.xit.foundation.AbstractComponent;
import cokr.xit.foundation.data.DataObject;

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

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

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

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

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

	/**지정한 조건에 따라 의견제출 대장 목록을 조회하여 반환한다.
	 * @param req 의견제출 대장 조회 조건
	 * @return 의견제출 대장 목록
	 */
	public List<DataObject> getOpnnSbmsnList(ExclQuery req) {
		if (req.getOrderBy() == null) {
			req.setOrderBy("REG_DT");
		}

		return opnnSbmsnMapper.selectOpnnSbmsnList(req);
	}

	/**지정한 조건에 따라 의견제출 대장 객체들을 반환한다.
	 * @param req 의견제출 대장 조회 조건
	 * @return 의견제출 대장 객체 목록
	 */
	public List<DataObject> getOpnnSbmsns(ExclQuery req) {
		if (req.getOrderBy() == null) {
			req.setOrderBy("REG_DT DESC, OPNN_ID DESC");
		}

		return opnnSbmsnMapper.selectOpnnSbmsns(req);
	}

	/**지정한 ID의 의견제출 정보를 반환한다.<br />
	 * @param opnnId 의견제출 ID
	 * @return 의견제출 정보
	 */
	public DataObject getOpnnSbmsnInfo(ExclQuery req) {
		return opnnSbmsnMapper.selectOpnnSbmsnInfo(req);
	}

	/**지정한 단속 ID의 단속 정보를 반환한다.<br />
	 * @param crndId 단속 ID
	 * @return 단속 정보
	 */
	public DataObject getCrdnInfo(ExclQuery req) {
		DataObject dataCrdn = opnnSbmsnMapper.selectCrdn(req);					// 단속ID로 단속, 의견제출 조회

		if (req.getCallPurpose().equals("create")) {
			dataCrdn.set("RCPT_YMD", dataCrdn.string("TODAY"));					// 접수 일자
			dataCrdn.set("RCPT_NO", dataCrdn.string("NEW_RCPT_NO"));			// 접수 번호
		}

		return dataCrdn;
	}

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

		// 단속 ID로 단속, 의견제출 정보 조회
		DataObject infoCrdnOpnnSbmsn = opnnSbmsnMapper.selectCrdnInfo(opnnSbmsn.getCrdnId());

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

		// 의견제출 대장 필수값 입력
		opnnSbmsn.setOpnnSbmsnSttsCd("00"); 										// 의견 제출 상태 코드 00:접수

		// 의견제출 대장을 등록 한다.
		retSuccess = opnnSbmsnMapper.insert(opnnSbmsn);
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("의견제출 대장 등록에 실패하였습니다.");
		}

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

			fileBean.create(fileInfoList);
		}

		// 단속 상태 코드가 사전통보중 이전일때만 단속의 상태를 의견제출 중으로 수정 한다.
		if (infoCrdnOpnnSbmsn.number("CRDN_STTS_CD").intValue() <= 42) {	// 사전통보 완료
			// 단속상태이력(TB_CRDN_STTS_HSTRY)
			CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();

			crdnSttsHstry.setCrdnId(infoCrdnOpnnSbmsn.string("CRDN_ID"));
			crdnSttsHstry.setBfrSttsCd(infoCrdnOpnnSbmsn.string("CRDN_STTS_CD"));
			crdnSttsHstry.setBfrSttsChgDt(infoCrdnOpnnSbmsn.string("CRDN_STTS_CHG_DT"));
			crdnSttsHstry.setCrdnSttsCd("31");									// 의견제출 접수
			crdnSttsHstry.setTaskDtlId(opnnSbmsn.getOpnnId());

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

		// 단속 대장(TB_CRDN) 의견제출여부(OPNN_SBMSN_YN) 정보를 수정 한다.
		Crdn crdn = new Crdn();

		crdn.setCrdnId(infoCrdnOpnnSbmsn.string("CRDN_ID"));
		crdn.setOpnnSbmsnYn("Y");

		retSuccess = opnnSbmsnMapper.updateCrdn(crdn);							// 단속 대장 수정
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("의견제출 등록 중 단속대장의 의견제출여부 수정에 실패하였습니다.");
		}

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

		return retMessage;
	}

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

		// 의견제출 첨부파일 등록
		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);										// 첨부파일 재 정렬
			}
		}

		// 의견제출 대장을 수정 한다.
		retSuccess = opnnSbmsnMapper.update(opnnSbmsn);
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("의견제출 대장 수정에 실패하였습니다.");
		}

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

		return retMessage;
	}

	/**의견제출 대장 심의(답변) 정보를 수정한다.
	 * @param opnnSbmsn 의견제출 대장
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public String updateOpnnSbmsnAnswer(OpnnSbmsn opnnSbmsn) {
		// 변수 선언
		boolean retSuccess = false;						// DB 처리 결과
		String retMessage = "";							// 처리 결과 메시지
		String newCrdnSttsCd = "";						// 신규 단속 상태 코드(CRDN_STTS_CD)

		// 의견제출(TB_OPNN_SBMSN) 자료 조회
		ExclQuery exclQuery = new ExclQuery();

		exclQuery.setOpnnId(opnnSbmsn.getOpnnId());
		exclQuery.setDelYn("N");

		// 의견제출(TB_OPNN_SBMSN) 자료 조회
		DataObject infoCrdnOpnnSbmsn = opnnSbmsnMapper.selectOpnnSbmsnInfo(exclQuery);

        // 수납 또는 취소된 자료를 의견제출 수용할 수 없다
		if (!infoCrdnOpnnSbmsn.string("CRDN_STTS_CD").equals("31") && !infoCrdnOpnnSbmsn.string("CRDN_STTS_CD").equals("82")) {
			retMessage = "[F] 작업 중 오류가 발생하였습니다.<br>현재 자료의 단속 상태가 " + infoCrdnOpnnSbmsn.string("CRDN_STTS_NM") + " 상태 입니다.";
			return retMessage;
		}

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

		// 조회된 의견제출상태 코드와 수정 할 의견제출상태 코드가 다르다면..
		if (!opnnSbmsn.getOpnnSbmsnSttsCd().equals(infoCrdnOpnnSbmsn.string("OPNN_SBMSN_STTS_CD"))) {
			if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("02")) {															// 수용
				newCrdnSttsCd = "82";											// 의견제출 수용
			} else if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("01") || opnnSbmsn.getOpnnSbmsnSttsCd().equals("03")
					|| opnnSbmsn.getOpnnSbmsnSttsCd().equals("04") || opnnSbmsn.getOpnnSbmsnSttsCd().equals("05")) {	// 미수용, 자진취하, 과태료감경, 심의제외
				// 단속 상태 이력(TB_CRDN_STTS_HSTRY) 자료 조회
				DataObject infoCrdnSttsHstry = crdnSttsHstryBean.getCrdnSttsHstryInfo(infoCrdnOpnnSbmsn.string("CRDN_ID"), "31");

				newCrdnSttsCd = infoCrdnSttsHstry.string("BFR_STTS_CD");		// 이전 단속상태코드 유지
			} else if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("06")) {
				newCrdnSttsCd = "87";											// 경찰서 이첩
			} else if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("00")) {
				newCrdnSttsCd = "31";
			} else {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("의견제출 심의 처리중 지정되지 않은 심의 상태가 입력되었습니다.");
			}

			if (infoCrdnOpnnSbmsn.string("RDUCT_ID").equals("")) {
				if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("04")) {
					Rduct rduct = new Rduct();

					rduct.setCrdnId(infoCrdnOpnnSbmsn.string("CRDN_ID"));
					rduct.setRtpyrId(infoCrdnOpnnSbmsn.string("RTPYR_ID"));
					rduct.setRductYmd(opnnSbmsn.getAnsYmd());
					rduct.setRductRsnCd(opnnSbmsn.getRductRsnCd());
					rduct.setRductAmt(opnnSbmsn.getRductAmt());
					rduct.setEtcCn("의견제출 심의 처리에 의한 감경 등록");

					retMessage = levy02Bean.createRduct(rduct);
					if (retMessage.contains("[F]")) {
						// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
						throw new RuntimeException("의견제출 심의 처리 중 과태료 감경 등록(수정)에 실패하였습니다.");
					}
				}
			} else {
				Rduct rduct = new Rduct();

				// 의견제출로 인한 감경인지 확인
				if (infoCrdnOpnnSbmsn.string("RDUCT_ETC_CN").contains("의견제출 심의 처리")) {
					if (opnnSbmsn.getOpnnSbmsnSttsCd().equals("04")) {
						rduct.setRductId(infoCrdnOpnnSbmsn.string("RDUCT_ID"));
						rduct.setRductYmd(opnnSbmsn.getAnsYmd());
						rduct.setRductRsnCd(opnnSbmsn.getRductRsnCd());
						rduct.setRductAmt(opnnSbmsn.getRductAmt());

						retMessage = levy02Bean.updateRduct(rduct);
						if (retMessage.contains("[F]")) {
							// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
							throw new RuntimeException("의견제출 심의 처리 중 과태료 감경 등록(수정)에 실패하였습니다.");
						}
					} else {
						rduct.setRductId(infoCrdnOpnnSbmsn.string("RDUCT_ID"));
						rduct.setDelRsn("의견제출 심의 처리에 의한 감경 삭제");

						retMessage = levy02Bean.removeRduct(rduct);
						if (retMessage.contains("[F]")) {
							// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
							throw new RuntimeException("의견제출 심의 처리 중 과태료 감경 등록(수정)에 실패하였습니다.");
						}
					}
				}
			}

			// 단속상태이력(TB_CRDN_STTS_HSTRY) 변경
			CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();

			crdnSttsHstry.setCrdnId(infoCrdnOpnnSbmsn.string("CRDN_ID"));
			crdnSttsHstry.setBfrSttsCd(infoCrdnOpnnSbmsn.string("CRDN_STTS_CD"));
			crdnSttsHstry.setBfrSttsChgDt(infoCrdnOpnnSbmsn.string("CRDN_STTS_CHG_DT"));
			crdnSttsHstry.setCrdnSttsCd(newCrdnSttsCd);
			crdnSttsHstry.setTaskDtlId(opnnSbmsn.getOpnnId());

			// 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장에 등록 한다.
			retSuccess = crdnSttsHstryBean.createHstryUpdateCrdnSttsCd(crdnSttsHstry);
			if (!retSuccess) {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("의견제출 심의(답변) 처리 중 단속대장의 단속상태코드 수정에 실패하였습니다.");
			}
		}

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

		return retMessage;
	}

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

		// 의견제출(TB_OPNN_SBMSN) 자료 조회
		ExclQuery exclQuery = new ExclQuery();

		exclQuery.setOpnnId(opnnSbmsn.getOpnnId());
		exclQuery.setDelYn("N");

		DataObject infoCrdnOpnnSbmsn = opnnSbmsnMapper.selectOpnnSbmsnInfo(exclQuery);

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

        fileBean.remove(OpnnSbmsn.INF_TYPE, deleteFiles);

		// 의견제출(TB_OPNN_SBMSN) 대장을 삭제 한다.
		retSuccess = opnnSbmsnMapper.delete(opnnSbmsn);
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("의견제출 대장 삭제에 실패하였습니다.");
		}

		// 단속 상태 코드가 의견제출 접수(31) 또는 의견제출 수용(82) 이라면... 이전 단속 상태 코드로 복원 한다.
		if (infoCrdnOpnnSbmsn.string("CRDN_STTS_CD").equals("31") || infoCrdnOpnnSbmsn.string("CRDN_STTS_CD").equals("82")) {
			// 단속 상태 이력(TB_CRDN_STTS_HSTRY) 대장을 삭제 한다.
			retSuccess = crdnSttsHstryBean.removeHstryUpdateCrdnSttsCd(infoCrdnOpnnSbmsn.string("CRDN_ID"), "92");
			if (!retSuccess) {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("의견제출 삭제 중 단속상태 변경에 실패하였습니다.");
			}
		}

		// 단속 대장(TB_CRDN) 의견제출여부(OPNN_SBMSN_YN) 정보를 수정 한다.
		Crdn crdn = new Crdn();

		crdn.setCrdnId(infoCrdnOpnnSbmsn.string("CRDN_ID"));
		crdn.setOpnnSbmsnYn("N");

		retSuccess = opnnSbmsnMapper.updateCrdn(crdn);							// 단속 대장 수정
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("의견제출 삭제 중 단속대장의 의견제출여부 수정에 실패하였습니다.");
		}

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

		return retMessage;
	}

}
