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

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import cokr.xit.base.code.dao.CodeMapper;
import cokr.xit.base.code.service.CodeQuery;
import cokr.xit.base.file.FileInfo;
import cokr.xit.base.file.FileInfo.Relation;
import cokr.xit.base.file.service.FileQuery;
import cokr.xit.base.file.service.bean.FileBean;
import cokr.xit.base.file.web.FileInfoFactory;
import cokr.xit.fims.cmmn.CrdnPayerHstry;
import cokr.xit.fims.cmmn.CrdnSttsHstry;
import cokr.xit.fims.cmmn.dao.CrdnPayerHstryMapper;
import cokr.xit.fims.cmmn.dao.CrdnSttsHstryMapper;
import cokr.xit.fims.crdn.Crdn;
import cokr.xit.fims.crdn.CrdnQuery;
import cokr.xit.fims.crdn.dao.CrdnInfoMapper;
import cokr.xit.fims.crdn.dao.CrdnUpdtMapper;
import cokr.xit.fims.crdn.service.bean.CrdnStngBean;
import cokr.xit.fims.cvlc.CrdnCvlcpt;
import cokr.xit.fims.cvlc.dao.AnswerWordsMapper;
import cokr.xit.fims.cvlc.dao.CrdnCvlcptMapper;
import cokr.xit.fims.cvlc.dao.WarningWordsMapper;
import cokr.xit.fims.excl.LevyExcl;
import cokr.xit.fims.excl.dao.LevyExclMapper;
import cokr.xit.foundation.AbstractComponent;
import cokr.xit.foundation.UserInfo;
import cokr.xit.foundation.data.DataObject;

/** 민원 부 기능 Bean
 * @author leebj
 */
@Component("crdnCvlcptSubBean")
public class CrdnCvlcptSubBean extends AbstractComponent {

	@Resource(name = "crdnCvlcptMapper")
	private CrdnCvlcptMapper crdnCvlcptMapper;

	@Resource(name = "crdnInfoMapper")
	private CrdnInfoMapper crdnInfoMapper;

	@Resource(name = "crdnUpdtMapper")
	private CrdnUpdtMapper crdnUpdtMapper;

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

	@Resource(name = "fileBean")
	private FileBean fileBean;

	@Resource(name = "codeMapper")
	private CodeMapper codeMapper;

	@Resource(name = "levyExclMapper")
	private LevyExclMapper levyExclMapper;

	@Resource(name = "answerWordsMapper")
	private AnswerWordsMapper answerWordsMapper;

	@Resource(name = "crdnPayerHstryMapper")
	private CrdnPayerHstryMapper crdnPayerHstryMapper;

	@Resource(name = "crdnSttsHstryMapper")
	private CrdnSttsHstryMapper crdnSttsHstryMapper;

	@Resource(name = "warningWordsMapper")
	private WarningWordsMapper warningWordsMapper;

	/**단속 대장 정보를 수정한다.
	 * @param nonQueryRequest 수정 요청, crdn 단속 대장
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public boolean updateCrdn(Map<String, Object> nonQueryRequest, Crdn crdn) {
		DataObject params = new DataObject();
		UserInfo userInfo = currentUser();
		params.set("currentUser", userInfo);
		params.set("crdn", crdn);
		for(String key : nonQueryRequest.keySet()){
			params.set(key, nonQueryRequest.get(key));
        }

		if(crdnCvlcptMapper.updateCrdn(params) != 1) {
			return false;
		}
		return crdnCvlcptMapper.updateCrdnAddition(params) == 1 ? true : false;
	}

	/**지정한 단속자료를 복사 등록 처리한다.
	 * @param crdnId 단속 ID
	 * @return 복사자료의 단속 ID
	 */
	public String insertCrdnFromSelect(String crdnId) {

		DataObject params = new DataObject();
		UserInfo userInfo = currentUser();
		params.set("currentUser", userInfo);
		params.set("crdnId", crdnId);

		if(crdnCvlcptMapper.insertCrdnFromSelect(params) != 1) {
			throw new RuntimeException("단속자료 복사 등록 중 단속대장 등록에 실패하였습니다.");
		}

		if(crdnCvlcptMapper.insertCrdnAdditionFromSelect(params) != 1) {
			throw new RuntimeException("단속자료 복사 등록 중 단속대장 등록에 실패하였습니다.");
		}

		return (String)params.get("newCrdnId");
	}

	/** 계도문 문구 설정 정보를 조회한다.
	 * @param crdnQuery 조회조건
	 * @return 계도문 문구 설정
	 */
	public List<DataObject> selectWarningWordsList(CrdnQuery crdnQuery) {

		return warningWordsMapper.selectWarningWordsList(crdnQuery);
	}

	/** 계도문 문구 설정 정보를 저장한다.
	 * @param crdnCvlcpt 문구 정보
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public boolean saveWarningWordsInfo(CrdnCvlcpt crdnCvlcpt) {
		if(ifEmpty(crdnCvlcpt.getAnsWordsId(), ()-> "").equals("")) {

			CodeQuery codeQuery = new CodeQuery();
			codeQuery.setGroupIDs("FIM022");
			codeQuery.setCodes(crdnCvlcpt.getAnsRsnCd());
			List<DataObject> codeList = codeMapper.getCodeList(codeQuery);
			crdnCvlcpt.setAnsRsnNm(codeList.get(0).string("CODE_VAL"));

			return warningWordsMapper.insertWarningWordsInfo(crdnCvlcpt) == 1 ? true : false;
		} else {
			return warningWordsMapper.updateWarningWordsInfo(crdnCvlcpt) == 1 ? true : false;
		}
	}

	/** 민원초기자료 상세화면에서 입력한 값대로 단속정보,납부자정보를 수정한다.
	 * @param nonQueryRequest 수정 요청, crdn 단속정보, 파일정보 newFileInfoList
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */

	public boolean updateSubInfo(Map<String, Object> nonQueryRequest, Crdn crdn,
			List<FileInfo> newFileInfoList) {

		boolean saved = false;

		DataObject crdnInfo = crdnInfoMapper.selectCrdnInfo(crdn.getCrdnId());


		String acceptType = (String)ifEmpty(nonQueryRequest.get("acceptType"), "");


		//첨수파일 수 변경
		int fileInsertCnt = 0;
		int fileDeleteCnt = 0;
		if(newFileInfoList != null && !newFileInfoList.isEmpty()) {
			fileInsertCnt = newFileInfoList.size();
		}
		String[] deleteFileKeyList = (String[])ifEmpty(nonQueryRequest.get("deleteFileKeyList"), new String[] {});
		if(deleteFileKeyList.length > 0) {
			fileDeleteCnt = deleteFileKeyList.length;
		}
		int changeFileCnt = (fileInsertCnt - fileDeleteCnt);
		nonQueryRequest.put("changeFileCnt", changeFileCnt);

		//금액 변경
		if(crdnInfo.string("TASK_SE_CD").equals("PVS") && "Y".equals(crdnInfo.string("OVTIME_PRTTN_YN"))) {
			nonQueryRequest.put("changeAmountYn","N");
		} else {
			int[] basicAmt = crdnStngBean.getBasicAmt(crdn);
			int ffnlgCrdnAmt = crdnInfo.number("FFNLG_CRDN_AMT").intValue();
			if(ffnlgCrdnAmt != basicAmt[0]){
				nonQueryRequest.put("changeAmountYn","Y");
				crdn.setFfnlgCrdnAmt(basicAmt[0]);
				crdn.setFfnlgAmt(basicAmt[0]);
				crdn.setAdvntceAmt(basicAmt[1]);
				crdn.setFfnlgRductRt("0");
			} else {
				nonQueryRequest.put("changeAmountYn","N");
			}
		}

		//납부자 변경
		if(!crdnInfo.string("RTPYR_ID").equals(crdn.getRtpyrId())) {
			nonQueryRequest.put("changePayerYn","Y");
		} else {
			nonQueryRequest.put("changePayerYn","N");
		}

		//단속상태값 변경
		nonQueryRequest.put("changeStatusYn","Y");
		if(acceptType.equals("accept")) {
			if(!crdnInfo.string("CRDN_REG_SE_CD").equals("02")
					|| Arrays.asList(new String[]{"04","05","06"}).contains(crdnInfo.string("CVLCPT_TRSM_CD"))) {
				crdn.setCrdnSttsCd("22");
			} else {
				crdn.setCrdnSttsCd("21");
			}

		} else if(acceptType.equals("someAccept")){
			crdn.setCrdnSttsCd("83");
		} else if(acceptType.equals("nonAccept")) {
			crdn.setCrdnSttsCd("81");
		} else {
			throw new RuntimeException("단속민원답변 수정에 실패하였습니다.");
		}

		//부과 제외 대장 등록
		String dtlTaskId = "";
		if(acceptType.equals("someAccept") || acceptType.equals("nonAccept")) { //일부수용,불수용
			boolean retSuccess = false;
			LevyExcl excl01 = new LevyExcl();
			excl01.setCrdnId(crdn.getCrdnId());
			excl01.setSggCd(crdn.getSggCd());
			excl01.setTaskSeCd(crdn.getTaskSeCd());
			excl01.setLevyExclYmd(crdn.getLevyExclYmd());
			excl01.setLevyExclSeCd(crdn.getLevyExclSeCd());
			excl01.setLevyExclRsnCd(crdn.getLevyExclRsnCd());
			excl01.setEtcCn(crdn.getEtcCn());

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

			dtlTaskId = excl01.getLevyExclId();
		} else {
			dtlTaskId = crdn.getCrdnId();
		}

		//단속정보변경
		saved = this.updateCrdn(nonQueryRequest, crdn);
		if(!saved) {
			throw new RuntimeException("단속민원답변 수정 중 단속정보변경에 실패하였습니다.");
		}

		//단속 납부자 변경 이력 등록
		if(((String)nonQueryRequest.get("changePayerYn")).equals("Y")) {
			CrdnPayerHstry crdnPayerHstry = new CrdnPayerHstry();

			crdnPayerHstry.setCrdnId(crdn.getCrdnId());
			crdnPayerHstry.setRtpyrId(crdn.getRtpyrId());

			boolean retSuccess = crdnPayerHstryMapper.insert(crdnPayerHstry);
			if(!retSuccess) {
				throw new RuntimeException("단속민원답변 수정 중 단속납부자변경 이력 등록에 실패하였습니다.");
			}
		}

		//단속상태 변경 이력 등록
		if(((String)nonQueryRequest.get("changeStatusYn")).equals("Y")) {
			CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();

			crdnSttsHstry.setCrdnId(crdn.getCrdnId());
			crdnSttsHstry.setBfrSttsCd(crdnInfo.string("CRDN_STTS_CD"));
			crdnSttsHstry.setBfrSttsChgDt(crdnInfo.string("CRDN_STTS_CHG_DT"));
			crdnSttsHstry.setCrdnSttsCd(crdn.getCrdnSttsCd());
			crdnSttsHstry.setTaskDtlId(dtlTaskId);
			if(crdn.getCrdnSttsCd().equals("81") || crdn.getCrdnSttsCd().equals("83")) {
				crdnSttsHstry.setEtcCn("부과제외 대장 등록");
			} else {
				crdnSttsHstry.setEtcCn("민원 요청 수용");
			}

			boolean retSuccess = crdnSttsHstryMapper.insert(crdnSttsHstry);
			if(!retSuccess) {
				throw new RuntimeException("단속민원답변 수정 중 단속상태변경 이력 등록에 실패하였습니다.");
			}
		}

		//파일 처리
		if(newFileInfoList != null && !newFileInfoList.isEmpty()) {
			int fileInsertEffected = fileBean.create(newFileInfoList);
			if(fileInsertCnt != fileInsertEffected) {
				throw new RuntimeException("단속민원답변 수정 중 파일 등록에 실패하였습니다.");
			}
		}
		if(deleteFileKeyList.length > 0) {
			int fileDeleteEffected = fileBean.remove((String[])nonQueryRequest.get("deleteFileKeyList"));
			if(fileDeleteCnt != fileDeleteEffected) {
				throw new RuntimeException("단속민원답변 수정 중 파일 삭제에 실패하였습니다.");
			}
		}

		return true;
	}

	/** 단속자료를 복사하여 신규단속자료를 생성한다.
	 * @param crdnId 단속 ID
	 * @return 저장여부
	 */
	public boolean copyCvlcptCrdnInfo(String crdnId) {
		FileQuery fileQuery = new FileQuery().setInfoType(Crdn.INF_TYPE).setInfoKeys(crdnId);
		List<DataObject> orgnlCrdnFileList = fileBean.getFileList(fileQuery);


		String newCrdnId = this.insertCrdnFromSelect(crdnId);
		if(ifEmpty(newCrdnId, () -> "").equals("")) {
			throw new RuntimeException("단속민원 복사 등록 중 단속대장 등록에 실패하였습니다.");
		}


		if (!orgnlCrdnFileList.isEmpty() && orgnlCrdnFileList.size() > 0) {
			List<FileInfo> fileInfoList = new ArrayList<FileInfo>();

			List<File> files = new ArrayList<>();
			for (int iLoop = 0; iLoop < orgnlCrdnFileList.size(); iLoop++) {
				files.add(new File(orgnlCrdnFileList.get(iLoop).string("FILE_PATH")));
			}

			Relation relation = new Relation();
			relation.setInfoType(Crdn.INF_TYPE);
			relation.setInfoKey(newCrdnId);
			fileInfoList = new FileInfoFactory().createFileInfos(relation, files);
			for (int iLoop = 0; iLoop < fileInfoList.size(); iLoop++) {
				fileInfoList.get(iLoop).setName(orgnlCrdnFileList.get(iLoop).string("FILE_NM"));
			}
			int effected = fileBean.create(fileInfoList);
			if(effected == 0) {
				throw new RuntimeException("단속민원 복사 등록 중 파일복사에 실패하였습니다.");
			}
		}

		return true;
	}

	/** 단속자료에 대해 서손 처리한다.
	 * @param trigger 서손 실행 원인, crdnId 단속 ID
	 * @return 저장여부
	 */
	public boolean executelevyExcl(String trigger, String crdnId) {
		boolean saved = false;

		String levyExclRsnCd = "";
		String etcCn = "";

		DataObject crdnInfo = crdnInfoMapper.selectCrdnInfo(crdnId);
		if(trigger.equals("sendBack")) { //반송으로 인한 서손
			levyExclRsnCd = "191";
			etcCn = "이송(이첩)";
		} else if(trigger.equals("inquireTag")) { //표지조회실행으로 인한 서손
			levyExclRsnCd = "103";
			etcCn = "표지조회실행";
		} else {
			return false;
		}

		//부과제외 대장을 등록 한다.
		LevyExcl excl01 = new LevyExcl();
		excl01.setSggCd(crdnInfo.string("SGG_CD"));
		excl01.setTaskSeCd(crdnInfo.string("TASK_SE_CD"));
		excl01.setCrdnId(crdnInfo.string("CRDN_ID"));
		excl01.setLevyExclYmd((new SimpleDateFormat("yyyyMMdd")).format(new Date()));
		excl01.setLevyExclSeCd("1");
		excl01.setLevyExclRsnCd(levyExclRsnCd);
		excl01.setEtcCn(etcCn);
		saved = levyExclMapper.insert(excl01);
		if (!saved) {
			throw new RuntimeException("서손처리 중 부과제외 대장 등록에 실패하였습니다.");
		}

		//단속상태를 변경한다.
		Crdn crdn = new Crdn();
		crdn.setCrdnId(crdnId);
		crdn.setCrdnSttsCd("81");
		saved = crdnUpdtMapper.updateCrdnStatus(crdn) == 1 ? true : false;
		if (!saved) {
			throw new RuntimeException("서손처리 중 단속상태변경에 실패하였습니다.");
		}

		//단속상태 변경 이력 기록
		CrdnSttsHstry crdnSttsHstry = new CrdnSttsHstry();
		crdnSttsHstry.setCrdnId(crdnId);
		crdnSttsHstry.setBfrSttsCd(crdnInfo.string("CRDN_STTS_CD"));
		crdnSttsHstry.setBfrSttsChgDt(crdnInfo.string("CRDN_STTS_CHG_DT"));
		crdnSttsHstry.setCrdnSttsCd("81");
		crdnSttsHstry.setTaskDtlId(excl01.getLevyExclId());
		crdnSttsHstry.setEtcCn(etcCn);
		saved = crdnSttsHstryMapper.insert(crdnSttsHstry);
		if (!saved) {
			throw new RuntimeException("서손처리 중 단속상태이력 등록에 실패하였습니다.");
		}

		return true;
	}
}
