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.Rduct;
import cokr.xit.fims.levy.dao.RductMapper;
import cokr.xit.foundation.AbstractComponent;
import cokr.xit.foundation.data.DataObject;

/**과태료 감경 대장 정보 관리 Bean
 *
 * <p>상세 설명:
 *
 * <pre>
 * ============ 변경 이력 ============
 * 2023-08-30	JoJH 최초 작성
 * ================================
 * </pre>
 */
@Component("levy02Bean")
public class Levy02Bean extends AbstractComponent {

	/** 과태료 감경 대장 정보 DAO */
	@Resource(name = "rductMapper")
	private RductMapper rductMapper;

	@Resource(name = "crdnStngBean")
	private CrdnStngBean crdnStngBean;

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

		return rductMapper.selectRductList(req);

//		List<DataObject> dataObjectList = rductMapper.selectRductList(req);
//
//		Iterator<DataObject> iterator = dataObjectList.iterator();
//    	while(iterator.hasNext()) {
//    		DataObject dataObject = iterator.next();
//    		String state = dataObject.string("CRDN_STTS_CD");
//    		int advntceAmt = dataObject.number("ADVNTCE_AMT").intValue();
//    		int ffnlgAmt = dataObject.number("FFNLG_AMT").intValue();
//    		int minusAmt = dataObject.number("MINUS_AMT").intValue();
//    		int adtnAmt = dataObject.number("ADTN_AMT").intValue();
//    		int rcvmtAmt = dataObject.number("RCVMT_AMT").intValue();
//
//    		dataObject.set("BLNC", crdnStngBean.getBalance(state,advntceAmt,ffnlgAmt,minusAmt,adtnAmt,rcvmtAmt));
//        }
//
//		return dataObjectList;

	}

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

		return rductMapper.selectRducts(req);
	}

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

	/**지정한 단속 ID의 단속 정보를 반환한다.<br />
	 * @param req 과태료 감경 대장 조회 조건
	 * @return 단속 정보
	 */

	public DataObject getCrdnInfo(LevyQuery req) {
		DataObject dataCrdn = rductMapper.selectCrdn(req);

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

		return dataCrdn;
	}

	/**과태료 감경 대장 정보를 등록한다.
	 * @param rduct 과태료 감경 대장
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public String createRduct(Rduct rduct) {
		// 변수 선언
		boolean retSuccess = false;						// DB 처리 결과
		String retMessage = "";							// 처리 결과 메시지

		// 단속 ID로 단속, 감경 정보 조회
		DataObject infoCrdnRduct = rductMapper.selectCrdnInfo(rduct.getCrdnId());

		// 감경 ID가 있다면 이미 부과제외 자료가 존재하므로 종료..
		if (!infoCrdnRduct.string("RDUCT_ID").equals("")) {
			retMessage = "[F] 작업 중 이미 등록된 자료가 존재합니다.";
			return retMessage;
		}
		// 단속 상태 코드(CRDN_STTS_CD) 확인하여 부과(51) 이후라면..
		if (infoCrdnRduct.number("CRDN_STTS_CD").intValue() > 51) {
			retMessage = "[F] 작업 중 오류가 발생하였습니다.<br>현재 자료의 단속 상태가 " + infoCrdnRduct.string("CRDN_STTS_NM") + " 상태 입니다.";
			return retMessage;
		}
		// 부과 가산금(LEVY_ADAMT)이 있다면..
		if (infoCrdnRduct.number("LEVY_ADAMT").intValue() > 0) {
			retMessage = "[F] 작업 중 오류가 발생하였습니다.<br>부과 가산금이 존재합니다.";
			return retMessage;
		}

		// 과태료 감경(TB_RDUCT) 대장을 등록 한다.
		retSuccess = rductMapper.insert(rduct);
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("과태료 감경 대장 등록에 실패하였습니다.");
		}

		int ffnlgAmt = 0;				// 과태료 금액
		int advntceAmt = 0;				// 사전통지 금액

		ffnlgAmt = infoCrdnRduct.number("FFNLG_CRDN_AMT").intValue() - rduct.getRductAmt();				// 과태료 단속 금액 - 감경 금액
		advntceAmt = ffnlgAmt - (ffnlgAmt * infoCrdnRduct.number("ADVNTCE_RDUCT_RT").intValue() / 100);	// 과태료 금액 - (과태료 금액 * 사전통지 감경 율 / 100)

		// 단속(TB_CRDN) 대장을 수정 한다.
		Crdn crdn = new Crdn();

		crdn.setCrdnId(rduct.getCrdnId());										// 단속 ID
		crdn.setFfnlgRductRt(infoCrdnRduct.string("WKSN_RDUCT_RT"));			// 과태료 감경 율
		crdn.setFfnlgAmt(ffnlgAmt);												// 과태료 금액
		crdn.setAdvntceAmt(advntceAmt);											// 사전통지 금액

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

		// 부과 ID가 존재한다면 부과(TB_LEVY) 대장을 수정 한다.
		if (!infoCrdnRduct.string("LEVY_ID").equals("")) {
			// 가산금이 존재하는 확인
			if (infoCrdnRduct.number("LEVY_ADAMT").intValue() != 0 ) {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("감경 등록 중 부과 대장에 가산금이 발생하여 부과 대장 수정에 실패하였습니다.");
			}

			Levy levy = new Levy();

			levy.setLevyId(infoCrdnRduct.string("LEVY_ID"));						// 부과 ID
			levy.setFfnlgAmt(ffnlgAmt);												// 과태료 금액

			// 단속상태코드가 부과(51)면 과태료 금액, 부과 이전이라면 사전통지 금액으로..
			if (infoCrdnRduct.number("CRDN_STTS_CD").intValue() == 51) {
				levy.setLevyPcptax(ffnlgAmt);										// 부과 본세 = 과태료 금액
			} else {
				// 주정차위반, 전용차로위반 과태료
				if (infoCrdnRduct.string("TASK_SE_CD").equals("BPV") || infoCrdnRduct.string("TASK_SE_CD").equals("PVS")) {
					// 납기 일자 확인
					if (infoCrdnRduct.number("DUDT_YMD").intValue() >= infoCrdnRduct.number("TODAY").intValue()) {
						levy.setLevyPcptax(advntceAmt);								// 부과 본세 = 사전통지 금액
					} else {
						levy.setLevyPcptax(ffnlgAmt);								// 부과 본세 = 과태료 금액
					}
				} else {
					levy.setLevyPcptax(advntceAmt);									// 부과 본세 = 사전통지 금액
				}
			}

			int sumAmt = levy.getLevyPcptax() - infoCrdnRduct.number("RCVMT_PCPTAX").intValue() - infoCrdnRduct.number("RDCAMT_PCPTAX").intValue();
			levy.setSumAmt(sumAmt);													// 합계 금액 = 부과 본세 - 수납 본세 - 감액 본세

			retSuccess = rductMapper.updateLevy(levy);
			if (!retSuccess) {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("감경 등록 중 부과대장 금액 수정에 실패하였습니다.");
			}
		}

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

		return retMessage;
	}

	/**과태료 감경 대장 정보를 수정한다.
	 * @param rduct 과태료 감경 대장
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public String updateRduct(Rduct rduct) {
		// 변수 선언
		boolean retSuccess = false;						// DB 처리 결과
		String retMessagae = "";						// 처리 결과 메시지

		// 과태료 감경(TB_RDUCT) 대장을 수정 한다.
		retSuccess = rductMapper.update(rduct);
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("과태료 감경 대장 수정에 실패하였습니다.");
		}

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

		return retMessagae;
	}

	/**과태료 감경 대장 정보를 삭제한다.
	 * @param rduct 과태료 감경 대장
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public String removeRduct(Rduct rduct) {
		// 변수 선언
		boolean retSuccess = false;						// DB 처리 결과
		String retMessage = "";							// 처리 결과 메시지

		// 단속 ID로 단속, 감경 정보 조회
		LevyQuery req = new LevyQuery();

		req.setRductId(rduct.getRductId());
		req.setDelYn("N");

		DataObject infoCrdnRduct = rductMapper.selectCrdn(req);

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

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

		// 과태료 금액 변경
		int ffnlgAmt = 0;				// 과태료 금액
		int advntceAmt = 0;				// 사전통지 금액

		ffnlgAmt = infoCrdnRduct.number("FFNLG_CRDN_AMT").intValue();				// 과태료 단속 금액 - 감경 금액
		advntceAmt = ffnlgAmt - (ffnlgAmt * infoCrdnRduct.number("ADVNTCE_RDUCT_RT").intValue() / 100);	// 과태료 금액 - (과태료 금액 * 사전통지 감경 율 / 100)

		// 단속(TB_CRDN) 대장을 수정 한다.
		Crdn crdn = new Crdn();

		crdn.setCrdnId(infoCrdnRduct.string("CRDN_ID"));						// 단속 ID
		crdn.setFfnlgRductRt("0");												// 과태료 감경 율
		crdn.setFfnlgAmt(ffnlgAmt);												// 과태료 금액
		crdn.setAdvntceAmt(advntceAmt);											// 사전통지 금액

		retSuccess = rductMapper.updateCrdn(crdn);
		if (!retSuccess) {
			// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
			throw new RuntimeException("감경 취소 중 단속대장 금액 수정에 실패하였습니다.");
		}

		// 부과 ID가 존재한다면 부과(TB_LEVY) 대장을 수정 한다.
		if (!infoCrdnRduct.string("LEVY_ID").equals("")) {
			// 가산금이 존재하는 확인
			if (infoCrdnRduct.number("LEVY_ADAMT").intValue() != 0 ) {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("감경 취소 중 부과 대장에 가산금이 발생하여 부과 대장 수정에 실패하였습니다.");
			}

			Levy levy = new Levy();

			levy.setLevyId(infoCrdnRduct.string("LEVY_ID"));						// 부과 ID
			levy.setFfnlgAmt(ffnlgAmt);												// 과태료 금액

			// 단속상태코드가 부과(51)면 과태료 금액, 부과 이전이라면 사전통지 금액으로..
			if (infoCrdnRduct.number("CRDN_STTS_CD").intValue() == 51) {
				levy.setLevyPcptax(ffnlgAmt);										// 부과 본세 = 과태료 금액
			} else {
				// 주정차위반, 전용차로위반 과태료
				if (infoCrdnRduct.string("TASK_SE_CD").equals("BPV") || infoCrdnRduct.string("TASK_SE_CD").equals("PVS")) {
					// 납기 일자 확인
					if (infoCrdnRduct.number("DUDT_YMD").intValue() >= infoCrdnRduct.number("TODAY").intValue()) {
						levy.setLevyPcptax(advntceAmt);								// 부과 본세 = 사전통지 금액
					} else {
						levy.setLevyPcptax(ffnlgAmt);								// 부과 본세 = 과태료 금액
					}
				} else {
					levy.setLevyPcptax(advntceAmt);									// 부과 본세 = 사전통지 금액
				}
			}

			int sumAmt = levy.getLevyPcptax() + infoCrdnRduct.number("LEVY_ADAMT").intValue() + infoCrdnRduct.number("INSPY_INT").intValue()
						- infoCrdnRduct.number("RCVMT_PCPTAX").intValue() - infoCrdnRduct.number("RCVMT_ADAMT").intValue()
						- infoCrdnRduct.number("RDCAMT_PCPTAX").intValue() - infoCrdnRduct.number("RDCAMT_ADAMT").intValue();
			levy.setSumAmt(sumAmt);				// 합계 금액 = 부과 본세 + 부과 가산금 + 분납 이자 - 수납 본세 - 수납 가산금 - 감액 본세 - 감액 가산금

			retSuccess = rductMapper.updateLevy(levy);
			if (!retSuccess) {
				// 예외를 발생시켜서 오류메세지를 보내고 DB Rollback
				throw new RuntimeException("감경 등록 중 부과대장 금액 수정에 실패하였습니다.");
			}
		}

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

		return retMessage;
	}

}
