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

import java.io.File;
import java.util.ArrayList;
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.CrdnPayerAddrHstry;
import cokr.xit.fims.cmmn.CrdnSttsHstry;
import cokr.xit.fims.cmmn.dao.CrdnPayerAddrHstryMapper;
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.fims.mngt.service.bean.TaskProcessor;
import cokr.xit.fims.sprt.service.bean.MediaBean;
import cokr.xit.foundation.component.AbstractBean;
import cokr.xit.foundation.data.DataObject;

/** 민원 부 기능 Bean
 * @author leebj
 */
@Component("crdnCvlcptSubBean")
public class CrdnCvlcptSubBean extends AbstractBean {
	@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 = "mediaBean")
	private MediaBean mediaBean;
	@Resource(name = "codeMapper")
	private CodeMapper codeMapper;
	@Resource(name = "levyExclMapper")
	private LevyExclMapper levyExclMapper;
	@Resource(name = "answerWordsMapper")
	private AnswerWordsMapper answerWordsMapper;
	@Resource(name = "crdnPayerAddrHstryMapper")
	private CrdnPayerAddrHstryMapper crdnPayerAddrHstryMapper;
	@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()
			.set("currentUser", currentUser())
			.set("crdn", crdn);
		nonQueryRequest.forEach(params::set);

		if (crdnCvlcptMapper.updateCrdn(params) != 1)
			return false;
		return crdnCvlcptMapper.updateCrdnAddition(params) == 1;
	}

	/**지정한 단속자료를 복사 등록 처리한다.
	 * @param crdnId 단속 ID
	 * @return 복사자료의 단속 ID
	 */
	public String insertCrdnFromSelect(String crdnId) {
		DataObject params = new DataObject()
			.set("currentUser", currentUser())
			.set("crdnId", crdnId);

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

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

		return params.string("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 (isEmpty(crdnCvlcpt.getAnsWordsId())) {
			CodeQuery codeQuery = new CodeQuery()
				.setGroupIDs("FIM022")
				.setCodes(crdnCvlcpt.getAnsRsnCd());
			List<DataObject> codeList = codeMapper.getCodeList(codeQuery);
			crdnCvlcpt.setAnsRsnNm(codeList.get(0).string("CODE_VAL"));

			return warningWordsMapper.insertWarningWordsInfo(crdnCvlcpt) == 1;
		} else {
			return warningWordsMapper.updateWarningWordsInfo(crdnCvlcpt) == 1;
		}
	}

	/** 민원초기자료 상세화면에서 입력한 값대로 단속정보,납부자정보를 수정한다.
	 * @param nonQueryRequest 수정 요청, crdn 단속정보
	 * @return 저장 여부
	 * <ul><li>저장됐으면 true</li>
	 *     <li>그렇지 않으면 false</li>
	 * </ul>
	 */
	public boolean updateSubInfo(Map<String, Object> nonQueryRequest, Crdn crdn) {
		DataObject crdnInfo = crdnInfoMapper.selectCrdnInfo(crdn.getCrdnId());
		//금액 변경
		if (TaskProcessor.get().isAmountChangeable(crdnInfo)) {
			nonQueryRequest.put("changeAmountYn","N");
		} else {
			int[] basicAmt = crdnStngBean.getBasicAmt(crdn);
			int ffnlgCrdnAmt = toInt(crdnInfo.get("FFNLG_CRDN_AMT"));
			if (ffnlgCrdnAmt != basicAmt[0]){
				nonQueryRequest.put("changeAmountYn","Y");
				crdn.setFfnlgCrdnAmt(basicAmt[0]);
				crdn.setFfnlgAmt(basicAmt[0]);
				crdn.setAdvntceAmt(basicAmt[1]);
				crdn.setFfnlgRdcrt("0");
			} else {
				nonQueryRequest.put("changeAmountYn","N");
			}
		}

		//납부자 변경
		nonQueryRequest.put("changePayerYn", !crdnInfo.string("RTPYR_ID").equals(crdn.getRtpyrId()) ? "Y" : "N");
		//납부자 주소 변경
		nonQueryRequest.put("changePayerAddrYn", !crdnInfo.string("ADDR_SN").equals(crdn.getAddrSn()) ? "Y" : "N");
		//단속상태값 변경
		nonQueryRequest.put("changeStatusYn","Y");

		String acceptType = blankIfEmpty(nonQueryRequest.get("acceptType"));
		String crdnSttsCd = switch (acceptType) {
		case "accept" -> "21";
		case "someAccept" -> "83";
		case "nonAccept" -> "81";
		default -> throw new RuntimeException("단속민원답변 수정에 실패하였습니다.");
		};
		crdn.setCrdnSttsCd(crdnSttsCd);

		//부과 제외 대장 등록
		String dtlTaskId = "";
		if (acceptType.equals("someAccept") || acceptType.equals("nonAccept")) { //일부수용,불수용
			LevyExcl excl01 = new LevyExcl();
			excl01.setCrdnId(crdn.getCrdnId());
			excl01.setSggCd(crdn.getSggCd());
			excl01.setLevyExclYmd(crdn.getLevyExclYmd());
			excl01.setLevyExclSeCd(crdn.getLevyExclSeCd());
			excl01.setLevyExclRsnCd(crdn.getLevyExclRsnCd());
			excl01.setEtcCn(crdn.getEtcCn());
			boolean success = levyExclMapper.insertLevyExcl(excl01) == 1;
			if (!success)
				throw new RuntimeException("부과제외 대장 등록에 실패하였습니다.");

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

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

		//단속 납부자 주소 변경 이력 등록
		if ("Y".equals(nonQueryRequest.get("changePayerYn")) ||
		    "Y".equals(nonQueryRequest.get("changePayerAddrYn"))) {
			CrdnPayerAddrHstry crdnPayerAddrHstry = new CrdnPayerAddrHstry();

			crdnPayerAddrHstry.setCrdnId(crdn.getCrdnId());
			crdnPayerAddrHstry.setRtpyrId(crdn.getRtpyrId());
			crdnPayerAddrHstry.setAddrSn(crdn.getAddrSn());

			int rtnNocs = crdnPayerAddrHstryMapper.insertCrdnPayerAddrHstry(crdnPayerAddrHstry);
			if (rtnNocs != 1)
				throw new RuntimeException("단속민원답변 수정 중 단속납부자변경 이력 등록에 실패하였습니다.");
		}

		//단속상태 변경 이력 등록
		if ("Y".equals(nonQueryRequest.get("changeStatusYn"))) {
			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);
			crdnSttsHstry.setEtcCn("81,83".contains(crdn.getCrdnSttsCd()) ? "부과제외 대장 등록" : "민원 요청 수용");

			int rtnNocs = crdnSttsHstryMapper.insertCrdnSttsHstry(crdnSttsHstry);
			if (rtnNocs != 1)
				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 = insertCrdnFromSelect(crdnId);
		if (isEmpty(newCrdnId))
			throw new RuntimeException("단속민원 복사 등록 중 단속대장 등록에 실패하였습니다.");

		if (!orgnlCrdnFileList.isEmpty()) {
			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);
			ArrayList<String> oldFileIdList = new ArrayList<>();
			for (int iLoop = 0; iLoop < fileInfoList.size(); iLoop++) {
				oldFileIdList.add(orgnlCrdnFileList.get(iLoop).string("FILE_ID"));
				fileInfoList.get(iLoop).setName(orgnlCrdnFileList.get(iLoop).string("FILE_NM"));
			}
			int affected = fileBean.create(fileInfoList);
			if (affected == 0)
				throw new RuntimeException("단속민원 복사 등록 중 파일복사에 실패하였습니다.");

			try {
				for (int iLoop = 0; iLoop < fileInfoList.size(); iLoop++) {
					mediaBean.copyMosaicInfo(oldFileIdList.get(iLoop), fileInfoList.get(iLoop).getId());
				}
			} catch (Exception e) {
				throw new RuntimeException("단속민원 복사 등록 중 사진 모자이크 정보 복사에 실패하였습니다.");
			}
		}

		return true;
	}

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

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

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

		//단속상태를 변경한다.
		Crdn crdn = new Crdn();
		crdn.setCrdnId(crdnId);
		crdn.setCrdnSttsCd("81");
		saved = crdnUpdtMapper.updateCrdnStatus(crdn) == 1;
		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.insertCrdnSttsHstry(crdnSttsHstry) == 1;
		if (!saved)
			throw new RuntimeException("서손처리 중 단속상태이력 등록에 실패하였습니다.");

		return true;
	}
}