package itn.let.schdlr.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;

import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import itn.com.cmm.EgovMultiPartEmail;
import itn.com.cmm.service.EgovFileMngService;
import itn.com.cmm.service.impl.FileManageDAO;
import itn.let.fax.user.service.impl.FaxDAO;
import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService;
import itn.let.mail.service.StatusResponse;
import itn.let.mjo.mjocommon.MjonCommon;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msg.service.RefundDTO;
import itn.let.mjo.msgdata.service.MjonMsgDataService;
import itn.let.mjo.msgdata.service.impl.MjonMsgDataDAO;
import itn.let.mjo.pay.service.MjonPayService;
import itn.let.mjo.pay.service.StVcVO;
import itn.let.mjo.payva.service.VacsAhstService;
import itn.let.mjo.payva.service.VacsAhstVO;
import itn.let.schdlr.service.SchdlrManageService;
import itn.let.schdlr.service.SchdlrVO;
import itn.let.sym.site.service.EgovSiteManagerService;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.uss.umt.service.EgovUserManageService;
import itn.let.uss.umt.service.UserManageVO;
import itn.let.utl.user.service.MjonNoticeSendUtil;

@Service("SchdlrManageService")
public class SchdlrManageServiceImpl extends EgovAbstractServiceImpl implements SchdlrManageService {

	@Resource(name = "egovItsmSchdlrGnrService")
	private EgovIdGnrService idgenSchdlrId;

	@Resource(name = "egovItsmSchdlrConfigGnrService")
	private EgovIdGnrService idgenSchCfgId;

	@Resource(name = "egovItsmSchdlrShareIdGnrService")
	private EgovIdGnrService idgenSchdlrShareId;

	@Resource(name = "SchdlrManageDAO")
	private SchdlrManageDAO schdlrManageDAO;

	@Resource(name = "FileManageDAO")
	private FileManageDAO fileMngDAO;

	@Resource(name = "EgovFileMngService")
	private EgovFileMngService fileMngService;

	@Resource(name = "egovMultiPartEmail")
	private EgovMultiPartEmail egovMultiPartEmail;

	@Value("#{globalSettings['Globals.mailContentFileFolder']}")
	private String MAIL_CONTENT_PATH;

	@Value("#{globalSettings['Globals.HOMPAGE_URL']}")
	private String HOMPAGE_URL;

	@Resource(name = "MjonMsgDataDAO")
	private MjonMsgDataDAO mjonMsgDataDAO;

	// 문자온 카카오 알림톡 발송 서비스
	@Resource(name = "kakaoAlimTalkService")
	private KakaoAlimTalkService kakaoAlimTalkService;

	// 문자온 문자 발송 서비스
	@Resource(name = "MjonMsgDataService")
	private MjonMsgDataService mjonMsgDataService;

	// 세틀뱅크 입금전문 서비스
	@Resource(name = "vacsAhstService")
	private VacsAhstService vacsAhstService;

	// 문자온 결제 서비스
	@Resource(name = "mjonPayService")
	private MjonPayService mjonPayService;

	/** userManageService */
	@Resource(name = "userManageService")
	private EgovUserManageService userManageService;

	/** 사이트 설정 */
	@Resource(name = "egovSiteManagerService")
	EgovSiteManagerService egovSiteManagerService;

	/** 알림전송 Util */
	@Resource(name = "mjonNoticeSendUtil")
	private MjonNoticeSendUtil mjonNoticeSendUtil;

	@Resource(name = "MjonCommon")
	private MjonCommon mjonCommon;

	@Resource(name = "faxDAO")
	public FaxDAO faxDao;

	private static final Logger LOGGER = LoggerFactory.getLogger(SchdlrManageServiceImpl.class);

	// 스케줄달력 목록(월별)
	public List<SchdlrVO> selectSchdlrList(SchdlrVO schdlrVO) throws Exception {
		return schdlrManageDAO.selectSchdlrList(schdlrVO);
	}

	// 스케줄 등록
	public void schdlrInsert(SchdlrVO schdlrVO) throws Exception {
		schdlrVO.setSchdlrId(idgenSchdlrId.getNextStringId()); // 신규 키
		schdlrManageDAO.schdlrInsert(schdlrVO); // 등록

		if (schdlrVO.getSchdlrUserId() != null && schdlrVO.getSchdlrUserId().length() != 0) {
			String userId[] = schdlrVO.getSchdlrUserId().split(",");
			String userName[] = schdlrVO.getSchdlrUserName().split(",");

			for (int i = 0; i < userId.length; i++) {
//				System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@   userID    : "+userId[i]);
//				System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@   userName    : "+userName[i]);
				schdlrVO.setSchdlrUserId(userId[i]);
				schdlrVO.setSchdlrUserName(userName[i]);
				schdlrVO.setSchdlrShareId(idgenSchdlrShareId.getNextStringId());
				schdlrManageDAO.schdlrShareInsert(schdlrVO);
			}
		}
	}

	// 스케줄 수정
	public void schdlrUpdate(SchdlrVO schdlrVO) throws Exception {
		schdlrManageDAO.schdlrUpdate(schdlrVO);

		if (!("").equals(schdlrVO.getSchdlrUserId())) {
			String userId[] = schdlrVO.getSchdlrUserId().split(",");
			String userName[] = schdlrVO.getSchdlrUserName().split(",");

			int schdlrShareCount = schdlrManageDAO.selectSchdlrShareCount(schdlrVO);

			if (schdlrShareCount != 0) {
				schdlrManageDAO.deleteSchdlrShare(schdlrVO.getSchdlrId());
			}

			for (int i = 0; i < userId.length; i++) {
//				System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@   userID    : "+userId[i]);
//				System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@   userName    : "+userName[i]);
				schdlrVO.setSchdlrUserId(userId[i]);
				schdlrVO.setSchdlrUserName(userName[i]);
				schdlrVO.setSchdlrShareId(idgenSchdlrShareId.getNextStringId());
				schdlrManageDAO.schdlrShareInsert(schdlrVO);
			}
		}
	}

	// 일정 상세 조회
	public SchdlrVO selectSchdlrDetail(SchdlrVO schdlrVO) throws Exception {
		return schdlrManageDAO.selectSchdlrDetail(schdlrVO);
	}

	@Override
	public List<SchdlrVO> selectSchdlrShare(SchdlrVO schdlrVO) throws Exception {
		return schdlrManageDAO.selectSchdlrShare(schdlrVO);
	}

	// 일정 목록 조회
	public List<SchdlrVO> selectSchList(SchdlrVO schdlrVO) throws Exception {
		return schdlrManageDAO.selectSchList(schdlrVO);
	}

	// 환경설정 등록
	public void insertSchConfig(SchdlrVO schdlrVO) throws Exception {
		schdlrVO.setSchdlrCfgId(idgenSchCfgId.getNextStringId()); // 신규 키
		schdlrManageDAO.insertSchConfig(schdlrVO); // 등록
	}

	// 환경설정 수정
	public void updateSchConfig(SchdlrVO schdlrVO) throws Exception {
		schdlrManageDAO.updateSchConfig(schdlrVO);
	}

	// 환경설정 상세 조회
	public SchdlrVO selectSchConfigDetail(SchdlrVO schdlrVO) throws Exception {
		SchdlrVO result = schdlrManageDAO.selectSchConfigDetail(schdlrVO);

		if (result == null) { // 첫 조회시 기본값 등록
			result = new SchdlrVO();
			result.setSchdlrCfgId(idgenSchCfgId.getNextStringId());
			result.setSchdlrCfgUserId(schdlrVO.getSchdlrCfgUserId());
			result.setSchdlrOpenCd("01");
			result.setSchdlrWeekBgnCd("01");
			result.setSchdlrTimeCd("01");
			result.setSchdlrColorUserCd("01");
			result.setSchdlrColorShareCd("02");
			result.setSchdlrColorPerCd("03");
			schdlrManageDAO.insertSchConfig(result);
		}

		return result;
	}

	// 일정 알림 메일 전송
	public void schMailSend(String bgnDateTime) throws Exception {
		List<SchdlrVO> mailList = schdlrManageDAO.selectMailSendList(bgnDateTime);

		for (SchdlrVO vo : mailList) {
			if (("").equals(vo.getEmailAdres()))
				continue;

			boolean result = sendMail(vo);
			LOGGER.debug("send succ update:", result);

			if (result)
				schdlrManageDAO.updateMailSend(vo);
		}
	}

	/**
	 * 일정 알림 메일 전송
	 * 
	 * @param SchdlrVO schdlrVO
	 * @return boolean
	 * @throws Exception
	 */
	private boolean sendMail(SchdlrVO schdlrVO) throws Exception {
		boolean result = false;
		try {
			String mailSj = "[" + schdlrVO.getSchdlrTitle() + "] N-CMS 스케줄러 일정 메일 알림입니다.";
			String alram = "";

//			// 알림설정 표시
//			if (Pattern.matches("^[0-9]*$", schdlrVO.getSchdlrAlarmCnd())) {
//				alram = schdlrVO.getSchdlrAlarmCnd() + " 분전";
//			} else if (schdlrVO.getSchdlrAlarmCnd().equals("etc")) {
//				alram = schdlrVO.getSchdlrAlarmDatetime();
//			}
			switch (schdlrVO.getSchdlrAlarmCnd()) {
			case "0":
				alram = "정시";
				break;
			case "10":
				alram = "십분 전";
				break;
			case "30":
				alram = "삼십분 전";
				break;
			case "60":
				alram = "한시간 전";
				break;
			case "etc":
				alram = schdlrVO.getSchdlrAlarmDatetime();
				break;
			}

			String mailContent = Jsoup
					.parse(new File(MAIL_CONTENT_PATH + "/direct/mail_template/sch_alrm_cont.html"), "UTF-8")
					.toString();
			mailContent = mailContent.replace("#일정명", schdlrVO.getSchdlrTitle());
			mailContent = mailContent.replace("#일시",
					schdlrVO.getSchdlrBgnDatetime() + " ~ " + schdlrVO.getSchdlrEndDatetime());
			mailContent = mailContent.replace("#장소", schdlrVO.getSchdlrPlace());
			mailContent = mailContent.replace("#내용", schdlrVO.getSchdlrCn().replaceAll("(\r\n|\r|\n|\n\r)", "<br>"));
			mailContent = mailContent.replace("#알림설정", alram);

			String resultMsg = egovMultiPartEmail.send(schdlrVO.getEmailAdres(), mailSj, "", mailContent);
//			egovMultiPartEmail.send(mailAddres, mailSj", mgs); // Simple Text Mail method

			result = true;
			LOGGER.debug("mail send resultMsg: ", resultMsg);
		} catch (Exception ex) {
			LOGGER.error("Sending Mail Exception : {} [unknown Exception]", ex.getCause());
			// LOGGER.error(ex.getMessage());
		}

		return result;
	}

	// 메인화면 > 전체일정
	public List<SchdlrVO> selectMainSchList(SchdlrVO schdlrVO) throws Exception {
		return schdlrManageDAO.selectMainSchList(schdlrVO);
	}

	// 문자온 문자발송 실패 건수 환불 배치(1주 대상)
	public void msgFailPayBack() throws Exception {

		Date now = new Date();
		System.out.println("문자온 실패 건수 환불 스케줄러 실행!!!(1weeks)" + now);
		/*
		 * 문자발송 실패 건수 확인 및 캐시 환불 처리
		 */
		mjonMsgDataService.selectMsgSentFailList();

		/*
		 * 세틀뱅크 입금 확인 및 캐시 충전 배치 프로세스
		 */
		/*
		 * VacsAhstVO vacsAhstVO = new VacsAhstVO(); List<VacsAhstVO>
		 * resultBeforCashList = vacsAhstService.selectBeforCashList(vacsAhstVO);
		 * 
		 * if(resultBeforCashList != null) {
		 * 
		 * for(VacsAhstVO temp : resultBeforCashList) {
		 * 
		 * StVcVO stvcVO = new StVcVO();
		 * 
		 * stvcVO.setOrgCd(temp.getOrgCd()); stvcVO.setBankCd(temp.getBankCd());
		 * stvcVO.setIacctNo(temp.getIacctNo()); stvcVO.setTrNo(temp.getTrNo());
		 * stvcVO.setTrIl(temp.getTrIl()); stvcVO.setTrAmt(temp.getTrAmt());
		 * stvcVO.setIacctNm(temp.getIacctNm()); stvcVO.setMberId(temp.getMberId());
		 * 
		 * //세틀뱅크 입금 내역 자동 충전하기 mjonPayService.insertVcCharge(stvcVO);
		 * 
		 * //세틀뱅크 입금 내역 원장에 처리 완료 내용 입력해 주기
		 * vacsAhstService.updateVacsAhstCashComplete(temp);
		 * 
		 * }
		 * 
		 * }
		 */

	}

	// 문자온 문자발송 실패 건수 환불 배치(31일)
	public void msgFailPayBackOneByDay() throws Exception {

		Date now = new Date();
		System.out.println("문자온 실패 건수 환불 스케줄러 실행!!!(31days)" + now);
		/*
		 * 문자발송 실패 건수 확인 및 캐시 환불 처리
		 */
//		mjonMsgDataService.selectMsgSentFailListOneByDay();

	}

	// 팩스 발송 실패 건수 환불 배치
	public void faxFailPayBack() throws Exception {

		System.out.println("팩스 실패 건수 환불 스케줄러 실행!!!" + new Date());

//		  팩스 발송 실패 건수 확인 및 캐시 환불 처리 
		faxDao.selectFaxSentFailList();
	}

	// 전용계좌 자동 충전 배치
	public void vacsAutoCharge() throws Exception {

		Date now = new Date();
		System.out.println("문자온 전용계좌  자동 충전 스케줄러 실행 !!!" + now);
		/*
		 * 문자발송 실패 건수 확인 및 캐시 환불 처리
		 */
		// mjonMsgDataService.selectMsgSentFailList();

		/*
		 * 세틀뱅크 입금 확인 및 캐시 충전 배치 프로세스
		 */
		VacsAhstVO vacsAhstVO = new VacsAhstVO();
		List<VacsAhstVO> resultBeforCashList = vacsAhstService.selectBeforCashList(vacsAhstVO);

		if (resultBeforCashList != null) {

			for (VacsAhstVO temp : resultBeforCashList) {

				StVcVO stvcVO = new StVcVO();

				stvcVO.setOrgCd(temp.getOrgCd());
				stvcVO.setBankCd(temp.getBankCd());
				stvcVO.setIacctNo(temp.getIacctNo());
				stvcVO.setTrNo(temp.getTrNo());
				stvcVO.setTrIl(temp.getTrIl());
				stvcVO.setTrAmt(temp.getTrAmt());
				stvcVO.setIacctNm(temp.getIacctNm());
				stvcVO.setMberId(temp.getMberId());

				// 세틀뱅크 입금 내역 자동 충전하기
				mjonPayService.insertVcCharge(stvcVO);

				// 세틀뱅크 입금 내역 원장에 처리 완료 내용 입력해 주기
				vacsAhstService.updateVacsAhstCashComplete(temp);

				try {
					String Userid = temp.getMberId();
					String mberNm = "";

					// 대상 : 휴대폰결제, 즉시이체, 전용계좌
					// Step 1. 스미싱의심 지정 여부
					JoinSettingVO joinSettingVO = new JoinSettingVO();
					joinSettingVO = egovSiteManagerService.selectAdminNotiDetail();
					if (joinSettingVO != null && joinSettingVO.getSmishingNoti().equals("Y")) {
						// Step 1. 개인회원 여부 체크
						int isPersnalMemberCnt = egovSiteManagerService.selectPersnalMemberCnt(Userid);
						if (isPersnalMemberCnt == 1) {
							// Step 2. 첫결제 여부 체크
							int isFirstPayCnt = egovSiteManagerService.selectFirstPayCnt(Userid);
							if (isFirstPayCnt == 1) {
								// SMS 체크
								if (joinSettingVO != null && joinSettingVO.getSmsNoti().equals("Y")) {
									// 스미싱의심 SMS 알림전송
									mjonNoticeSendUtil.smishingSmsNoticeSend("스미싱의심/전용계좌 첫결제", Userid, mberNm);
								}

								// SLACK 체크
								if (joinSettingVO != null && joinSettingVO.getSlackNoti().equals("Y")) {
									// Slack 메시지 발송(단순본문)
									String msg = "[문자온] 스미싱의심/전용계좌 첫결제 - " + mberNm + "(" + Userid + ")";
									mjonCommon.sendSimpleSlackMsg(msg);
								}

								// 스미싱 의심회원으로 변경
								UserManageVO userManageVO = new UserManageVO();
								userManageVO.setSmishingYn("Y");
								userManageVO.setMberId(Userid);
								userManageService.updateOneUserSmishingYnNotAlert(userManageVO);
							}
						}
					}

				} catch (Exception e) {
					System.out.println("#############################################################");
					System.out.println("전용계좌 슬랙알림 & 스미싱의심 처리 Error");
					System.out.println("전용계좌 TrNo : " + temp.getTrNo());
					System.out.println("전용계좌 e.getMessage() : " + e.getMessage());
				}

			}

		}

	}

	// 카카오 환불 처리 리스트
	public void kakaoFailPayBack() throws Exception {

		// 카카오 알림톡 환불 처리
		kakaoAlimTalkService.selectKakaoAtSentRefundList();

		// 카카오 친구톡 환불 처리
//		kakaoAlimTalkService.selectKakaoFtSentRefundList();

	}

	@Override
	public void payBack(String type, int limitCout) throws Exception {
		// 문자 환불
		if ("ONE".equals(type)) { // 하루에 한번만 31일 대상으로 실행
			msgFailPayBackOneByDay();

		} else { // 2분 마다는 7일을 대상으로 실행
			MjonMsgVO mjonMsgVO = new MjonMsgVO();
			mjonMsgVO.setRecordCountPerPage(limitCout);

			List<MjonMsgVO> msgFailList = mjonMsgDataDAO.selectMsgSentFailSchedulerList(mjonMsgVO);
			long forBeforeTime = System.currentTimeMillis(); // 코드 실행 전 시간
			int batchSize = 300;
			int totalSize = msgFailList.size();
			int endj = 0;
			for (int i = 0; i < totalSize; i += batchSize) {
				int end = Math.min(i + batchSize, totalSize);
				long beforeTime = System.currentTimeMillis(); // 코드 실행 전 시간
				for (int j = endj; j < end; j++) {
					System.out.println(j + " : " + end);
					try {
						mjonMsgDataDAO.updateMsgSentFailPayBack(msgFailList.get(j));
					} catch (Exception ex) {
						System.out.println("=============SchedulerUtil=====PayBack Catch =============>");
						System.out.println(msgFailList.get(j).getUserId() + "  :   "
								+ msgFailList.get(j).getMsgGroupId() + " :  " + msgFailList.get(j).getUserData());
						ex.printStackTrace();
					}
				}
				endj = end;

				long afterTime = System.currentTimeMillis(); // 코드 실행 후 시간
				long secDiffTime = (afterTime - beforeTime) / 1000; // 코드 실행 전후 시간 차이 계산(초 단위)
				System.out.println("==PayBack for 1 =============>  : " + secDiffTime + "초");
			}
			long forAfterTime = System.currentTimeMillis(); // 코드 실행 후 시간
			long forSecDiffTime = (forAfterTime - forBeforeTime) / 1000; // 코드 실행 전후 시간 차이 계산(초 단위)
			System.out.println(
					"==PayBack for 2 =============> 수량 : " + msgFailList.size() + "  =====  " + forSecDiffTime + "초");

		}
	}

	/**
	 * @methodName : refundTest
	 * @author : 이호영
	 * @date : 2024.12.12
	 * @description : 환불 데이터
	 * @param p_type
	 * @param request
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@Override
	public void payBack_advc(String p_type) throws Exception {
		
		List<MjonMsgVO> msgFailList = new ArrayList<>();
		msgFailList = getMsgFailList(p_type);

		// 리스트가 비어있는 경우 종료
		if (msgFailList == null || msgFailList.isEmpty() || msgFailList.size() < 1) {
			System.out.println("No payBack messages empty.");
		}else {
			
			try {
				// 필요한 필드만 DTO로 매핑
				List<RefundDTO> dtoList = msgFailList.stream()
														.map(msg -> 
																new RefundDTO(
																		msg.getUserId()
																		, msg.getMsgGroupId()
																		, msg.getUserData()
																		, Integer.parseInt(msg.getUserData())
																		, msg.getEachPrice())
															)
															.collect(Collectors.toList());
				
				// JSON 변환
				ObjectMapper objectMapper = new ObjectMapper();
				String msgFailListJson = objectMapper.writeValueAsString(dtoList);

				mjonMsgDataDAO.updateMsgSentFailPayBackBatch(msgFailListJson);

			} catch (Exception ex) {
				ex.printStackTrace();
			}
			
		}

		// TODO Auto-generated method stub

	}

	/**
	 * @methodName : getMsgFailList
	 * @author : 이호영
	 * @date : 2024.12.12
	 * @description : 파라미터에 따라 환불 데이터 가져오기
	 * @param p_type
	 * @return
	 * @throws Exception
	 */
	private List<MjonMsgVO> getMsgFailList(String p_type) throws Exception {
		List<MjonMsgVO> msgFailList = new ArrayList<>();
		// 문자 환불
		if ("ONE".equals(p_type)) { // 하루에 한번만 31일 대상으로 실행

			msgFailList = mjonMsgDataDAO.selectMsgSentFailListOneByDay();
		} else {
			// 10분 마다 1주일 데이터에서 환불 대상을 찾아서 환불 한다.
			// schdlrManageService.msgFailPayBack();

			msgFailList = mjonMsgDataDAO.selectMsgSentFailList();
		}

		return msgFailList;
	}
}
