package itn.let.mjo.mjocommon;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.mysql.jdbc.StringUtils;

import itn.com.cmm.MjonMsgSendVO;
import itn.com.cmm.OptimalMsgResultDTO;
import itn.com.cmm.util.MsgSendUtils;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.mail.service.StatusResponse;
import itn.let.mjo.event.service.MjonEventService;
import itn.let.mjo.event.service.MjonEventVO;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msgholiday.service.MsgAlarmSetVO;
import itn.let.mjo.msgholiday.service.MsgHolidayService;
import itn.let.mjo.msgholiday.service.MsgHolidayVO;
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 lombok.extern.slf4j.Slf4j;

@Slf4j
@Service("MjonCommon")
public class MjonCommon {
	

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

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

	@Resource(name = "MjonEventService")
	private MjonEventService mjonEventService;
	
	@Resource(name = "MsgHolidayService")
	private MsgHolidayService msgHolidayService;

	@Value("#{globalSettings['Globals.slack.hooks.url']}")
	private String SLACK_URL;
	
	/** xpedite 솔루션 ID*/
	@Value("#{globalSettings['Globals.slack.channel.name']}")
	private String SLACK_CHANNEL;
	
	

	

	/** 
	 * @methodName	: getAdminSandSlack 
	 * @author		: 이호영
	 * @date		: 2024.12.04 
	 * @description	: 기존 메소드 리펙토링
	 * @param mjonMsgVO 
	 */
	public void getAdminSandSlack(MjonMsgVO mjonMsgVO) {
	
		HttpClient client = new HttpClient();
		PostMethod post = new PostMethod(SLACK_URL);
	
		try {
			// 메시지 내용 설정
			String smsTxt = formatSmsText(mjonMsgVO);
			String sandName = formatSandName(mjonMsgVO);
		
			// Slack 메시지 생성
			JSONObject json = new JSONObject();
			json.put("channel", SLACK_CHANNEL);
			json.put("text", smsTxt);
			json.put("username", sandName);
		
			// Slack 요청
			post.addParameter("payload", json.toString());
			post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
		
			// Slack 응답 처리
			int responseCode = client.executeMethod(post);
			if (responseCode != HttpStatus.SC_OK) {
				log.warn("Slack 메시지 전송 실패. Response: {}", post.getResponseBodyAsString());
			}
	
		} catch (IllegalArgumentException e) {
			log.error("Slack 메시지 전송 중 IllegalArgumentException 발생", e);
		} catch (IOException e) {
			log.error("Slack 메시지 전송 중 IOException 발생", e);
		} catch (Exception e) {
			log.error("Slack 메시지 전송 중 Exception 발생", e);
		} finally {
			post.releaseConnection();
		}
	}
	
	/**
	* @throws Exception 
	 * @Method Name : getAdminSlackSand
	* @작성일 : 2022. 12. 6.
	* @작성자 :  WYH
	* @Method 설명 : slack 메시지 전송
	*/
	/*public void getAdminSandSlack(MjonMsgVO mjonMsgVO) {
		
		HttpClient client = new HttpClient();
		PostMethod post = new PostMethod(url);
		JSONObject json = new JSONObject();
		try {
 
			String reserveYn = mjonMsgVO.getReserveYn();
			String delayYn = mjonMsgVO.getDelayYn();
			String smsTxt = mjonMsgVO.getSmsTxt();
			String smishingYn = mjonMsgVO.getSmishingYn();
			String reservSmsTxt = "";
			String smisingSmsTxt = "";
			//예약문자를 발송하는 경우 문자 내용 앞에 "[예약]" 표시되도록 처리
			
			if(reserveYn.equals("Y")) {
				
				if(smishingYn.equals("Y") || delayYn.equals("Y")) {
					reservSmsTxt = "[스미싱의심][예약]" + smsTxt;
				}else {
					reservSmsTxt = "[예약]" + smsTxt;
				}
				
				smsTxt = reservSmsTxt;
				System.out.println("smishingYn : "+ smishingYn);
				System.out.println("delayYn : "+ delayYn);
			}else if(smishingYn.equals("Y") || delayYn.equals("Y")) {
				
				smisingSmsTxt = "[스미싱의심]" + smsTxt;
				smsTxt = smisingSmsTxt;
			}
			
			String sandName = mjonMsgVO.getCallFrom();
			String userId = mjonMsgVO.getUserId();
			String msgType = "";
			int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt());//그림 이미지 갯수
			if(mjonMsgVO.getMsgType().equals("4")) {	//단문 금액
				msgType = "[단문]";
			}else if(mjonMsgVO.getMsgType().equals("6")){
				if(fileCount == 0) {
					msgType = "[장문]";	
				}else {
					msgType = "[그림]";
					// 2022.12.21 JSP => 텍스트없는 그림문자만 발송시 슬랙알림 안됨
					if (StringUtils.isNullOrEmpty(smsTxt)) {
						smsTxt = "그림문자 " + smsTxt;
					}
				}
			}
//			sandName = "[" + userId + "]" + "[" + sandName + "]" + msgType;
			sandName = "[개발테스트]"+"[" + userId + "]" + "[" + sandName + "]" + msgType;
			
			json.put("channel", "mjon메시지");
			json.put("text", smsTxt);
			json.put("username", sandName);
			
			
			post.addParameter("payload", json.toString());
			// 처음에 utf-8로 content-type안넣어주니까 한글은 깨져서  content-type넣어줌
			post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			int responseCode = client.executeMethod(post);
			String response = post.getResponseBodyAsString();
			if (responseCode != HttpStatus.SC_OK) { 
				System.out.println("Response: " + response);
			}
		} catch (IllegalArgumentException e) {
			System.out.println("IllegalArgumentException posting to Slack " + e);
		} 
		catch (IOException e) {
			System.out.println("IOException posting to Slack " + e);
		} 
		catch (Exception e) {
			System.out.println("Exception posting to Slack " + e);
			e.printStackTrace();
		} finally {
			post.releaseConnection();
		}
		
	}*/
	
	
	/**
	* @Method Name : sendSimpleSlackMsg
	* @작성일 : 2022. 12. 9
	* @작성자 :  AnJooYoung
	* @Method 설명 : slack 단순 메시지 전송
	*/
	@SuppressWarnings("unchecked")
	public void sendSimpleSlackMsg(String msg) {
		
		HttpClient client = new HttpClient();
		PostMethod post = new PostMethod(SLACK_URL);
		JSONObject json = new JSONObject();
		try {
			
			json.put("channel", SLACK_CHANNEL);
			//json.put("channel", "C04DNV4FYP6");	//개발 서버용
			
			json.put("text", msg);
			
			post.addParameter("payload", json.toString());
			// 처음에 utf-8로 content-type안넣어주니까 한글은 깨져서  content-type넣어줌
			post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			int responseCode = client.executeMethod(post);
			String response = post.getResponseBodyAsString();
			if (responseCode != HttpStatus.SC_OK) { 
				System.out.println("Response: " + response);
			}
		} catch (IllegalArgumentException e) {
			System.out.println("IllegalArgumentException posting to Slack " + e);
		} catch (IOException e) {
			System.out.println("IOException posting to Slack " + e);
		} catch (Exception e) {
			System.out.println("Exception posting to Slack " + e);
		} finally {
			post.releaseConnection();
		}
		
	}
	
	
	/**
	 * 관리자로 문자 발송해주기
	 * 사용자가 보낸 문자를 문자온 법인폰으로 발송해주는 기능 함수.
	 * 일반문자 와 대량 문자 모두 적용하고 있음
	 * 2022.09.19 우영두 추가
	 * 2023.01.26 우영두 수정 => 대표전송사로 발송되도록 수정
	 * */
	public MjonMsgVO getAdminPhoneSendMsgDataComm(MjonMsgVO mjonMsgVO) throws Exception{
		
		try {
			mjonMsgVO.setUserId("system");//시스템 발송 문자로 처리
			
			//전송사 선택
			String msgType = mjonMsgVO.getMsgType();
			int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt());//그림 이미지 갯수
			
			if(msgType.equals("6")) {//장문 혹은 그림문자인 경우
				if(fileCount > 0) {//그림문자인 경우
					mjonMsgVO.setNeoType("4");
				}				
			}
			
			//수신번호가 배열로 되어있어서 배열에 담아준다.
			String[] phone = new String[1];
			String callTo = "15518011";
			phone[0] = callTo;
			mjonMsgVO.setCallToList(phone);//수신번호 리스트
			
			//시스템 로그용 수신 정보
			mjonMsgVO.setCallTo("help@iten.co.kr");
			
			//현재 고객의 보유 캐시가 문자 발송이 가능한 금액인지 체크
	    	//String userMoney = "0.0";
	    	String userPoint = "0.0";
	    	mjonMsgVO.setBefPoint(userPoint); //현재 보유 포인트 정보 저장
	    	mjonMsgVO.setBefCash("0.0");		//관리자가 발송하는 것이라서 0원으로 입력
	    	mjonMsgVO.setMsgGroupCnt("1");
	    	
	    	//문자종류 관리자가 발송하는 것은 msgKind : S 로 셋팅
			mjonMsgVO.setMsgKind("S");
			
			Date now = new Date();
			SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
			mjonMsgVO.setReqDate(sdFormat.format(now));
			
			//예약 문자 발송 없이 즉시 발송으로 처리
			mjonMsgVO.setReserveYn("N");
			
		} catch (Exception e) {
			System.out.println("+++++++++++++++++++++++++++++ MjonCommon Class getAdminPhoneSendMsgData Function Error !!!" + e);
		}
		
		return mjonMsgVO;
	}
	
	
	/**
	 * 관리자가 사용자에게 문자 발송해주기
	 * 발신번호 승인 / 반려시 사용자에게 문자 발송해 주기.
	 * 일반문자 와 대량 문자 모두 적용하고 있음
	 * 2022.09.26 우영두 추가
	 * 
	 * */
	public MjonMsgVO getAdminToMberPhoneSendMsgDataComm(MjonMsgVO mjonMsgVO) throws Exception{
		
		try {
			mjonMsgVO.setUserId("system");//시스템 발송 문자로 처리
			
			//전송사 선택
			String msgType = mjonMsgVO.getMsgType();
			int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt());//그림 이미지 갯수
			
			if(msgType.equals("6")) {//장문 혹은 그림문자인 경우
				if(fileCount > 0) {//그림문자인 경우
					mjonMsgVO.setNeoType("4");
				}
			}
			
			//수신번호가 배열로 되어있어서 배열에 담아준다.
			String[] phone = new String[1];
			String callTo = mjonMsgVO.getCallTo();
			phone[0] = callTo;
			mjonMsgVO.setCallToList(phone);//수신번호 리스트
			
			//시스템 로그용 수신 정보
			mjonMsgVO.setCallTo(callTo);
			
			//현재 고객의 보유 캐시가 문자 발송이 가능한 금액인지 체크
	    	//String userMoney = "0.0";
	    	String userPoint = "0.0";
	    	mjonMsgVO.setBefPoint(userPoint); //현재 보유 포인트 정보 저장
	    	mjonMsgVO.setBefCash("0.0");		//관리자가 발송하는 것이라서 0원으로 입력
	    	mjonMsgVO.setMsgGroupCnt("1");
	    	
	    	//문자종류 관리자가 발송하는 것은 msgKind : S 로 셋팅
			mjonMsgVO.setMsgKind("S");
			
			//예약 문자 발송 없이 즉시 발송으로 처리
			mjonMsgVO.setReserveYn("N");
			
		} catch (Exception e) {
			System.out.println("+++++++++++++++++++++++++++++ MjonCommon Class getAdminToMberPhoneSendMsgData Function Error !!!" + e);
		}
		
		return mjonMsgVO;
	}
	
	@SuppressWarnings("unchecked")
	public void getAdminKakaoAtSandSlack(KakaoVO kakaoVO) {
		
		HttpClient client = new HttpClient();
		PostMethod post = new PostMethod(SLACK_URL);
		JSONObject json = new JSONObject();
		try {
			
			String reserveYn = kakaoVO.getReserveYn();
			String atDelayYn = kakaoVO.getAtDelayYn();
			String smsTxt = kakaoVO.getTemplateContent();
			String reservSmsTxt = "";
			String smisingSmsTxt = "";
			//예약문자를 발송하는 경우 문자 내용 앞에 "[예약]" 표시되도록 처리
			if(reserveYn.equals("Y")) {
				
				if(atDelayYn.equals("Y")) {//예약문자 중 스미싱의심 일 경우
					reservSmsTxt = "[스미싱의심][예약]" + smsTxt;
				}else {
					reservSmsTxt = "[예약]" + smsTxt;
				}
				smsTxt = reservSmsTxt;
			}else if(atDelayYn.equals("Y")) {
				
				smisingSmsTxt = "[스미싱의심]" + smsTxt;
				smsTxt = smisingSmsTxt;
			}
			
			String sandName = kakaoVO.getCallFrom();
			String userId = kakaoVO.getUserId();
			String msgType = "";
			
			if(kakaoVO.getMsgType().equals("8")) {
				msgType = "[알림톡]";
			}else if(kakaoVO.getMsgType().equals("9")){
				msgType = "[친구톡]";
			}
			sandName = "[" + userId + "]" + "[" + sandName + "]" + msgType;
			
			json.put("channel", SLACK_CHANNEL);
			json.put("text", smsTxt);
			json.put("username", sandName);
			
			
			post.addParameter("payload", json.toString());
			// 처음에 utf-8로 content-type안넣어주니까 한글은 깨져서  content-type넣어줌
			post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			int responseCode = client.executeMethod(post);
			String response = post.getResponseBodyAsString();
			if (responseCode != HttpStatus.SC_OK) { 
				System.out.println("Response: " + response);
			}
		} catch (IllegalArgumentException e) {
			System.out.println("IllegalArgumentException posting to Slack " + e);
		} catch (IOException e) {
			System.out.println("IOException posting to Slack " + e);
		} catch (Exception e) {
			System.out.println("Exception posting to Slack " + e);
		} finally {
			post.releaseConnection();
		}
		
	}
	
	
	public String getCreateMsgUserIdgen(String subUserId, String lastId) throws Exception{
		
		String returnId = "";
		String[] splitId = lastId.split("_");
		
		if(splitId.length > 0) {
			
			int lastNum = Integer.parseInt(splitId[1]);
			
			lastNum = lastNum + 1;
			
			String tmpLastNum = Integer.toString(lastNum);
			
			int zeroPlusCnt = 14 - tmpLastNum.length();
			
			StringBuilder sb = new StringBuilder();
			sb.append(subUserId + "_");
			
			for(int i=0; i< zeroPlusCnt; i++) {
				
				sb.append('0');
				
			}
			
			sb.append(tmpLastNum);

			returnId = sb.toString();
			
		}
		
		return returnId;
	}



private String formatSmsText(MjonMsgVO mjonMsgVO) {
    String smsTxt = mjonMsgVO.getSmsTxt();
    String reserveYn = safeGetString(mjonMsgVO.getReserveYn());
    String delayYn = safeGetString(mjonMsgVO.getDelayYn());
    String smishingYn = safeGetString(mjonMsgVO.getSmishingYn());

    // 예약 문자와 스미싱 의심 처리
    if ("Y".equals(reserveYn)) {
        smsTxt = ("Y".equals(smishingYn) || "Y".equals(delayYn)) ? "[스미싱의심][예약]" + smsTxt : "[예약]" + smsTxt;
    } else if ("Y".equals(smishingYn) || "Y".equals(delayYn)) {
        smsTxt = "[스미싱의심]" + smsTxt;
    }

    // 그림 문자 처리
    int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0);
    if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isNullOrEmpty(smsTxt)) {
        smsTxt = "그림문자 " + smsTxt;
    }

    return smsTxt;
}

private String formatSandName(MjonMsgVO mjonMsgVO) {
    String userId = mjonMsgVO.getUserId();
    String callFrom = mjonMsgVO.getCallFrom();
    String msgType = getMessageTypeLabel(mjonMsgVO);

    return String.format("[%s][%s]%s", userId, callFrom, msgType);
}

private String getMessageTypeLabel(MjonMsgVO mjonMsgVO) {
    String msgType = mjonMsgVO.getMsgType();
    int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0);

    switch (msgType) {
        case "4":
            return "[단문]";
        case "6":
            return fileCount == 0 ? "[장문]" : "[그림]";
        default:
            return "";
    }
}


private int parseIntOrDefault(String value, int defaultValue) {
    try {
        return Integer.parseInt(value);
    } catch (NumberFormatException e) {
        return defaultValue;
    }
}
	
	
	
	

	// 전체 로직 처리 (한 번에 모든 필요한 정보 반환)
	public boolean processUserAndCheckSms(MjonMsgVO mjonMsgVO, String userId) throws Exception {
		UserManageVO userManageVO = getUserManageInfo(userId);

		// 기본값 처리된 사용자 정보와 문자 상태
		String adminSmsNoticeYn = userManageVO.getAdminSmsNoticeYn();
		String smishingYn = userManageVO.getSmishingYn();
		String spamStatus = safeGetString(mjonMsgVO.getSpamStatus());

		// 조건 체크
		if ("Y".equals(adminSmsNoticeYn) || "Y".equals(spamStatus) || "Y".equals(smishingYn)) {
			mjonMsgVO.setSmishingYn(smishingYn); // MjonMsgVO에 스미싱 정보 설정

			// 스미싱 알림 처리
			return handleSmishingAlert(mjonMsgVO); // 알림 처리 결과 반환
		}

		return false; // 알림 처리되지 않음
	}

	// 사용자 정보 조회 및 기본값 처리
	private UserManageVO getUserManageInfo(String userId) throws Exception {
//		UserManageVO userManageVO = new UserManageVO();
//		userManageVO.setAdminSmsNoticeYn("Y"); // 기본값
//		userManageVO.setSmishingYn("N"); // 기본값
//		
		return userManageService.selectAdminSmsNoticeYn(new UserManageVO(userId));
	}

	// 스미싱 알림 처리
	private boolean handleSmishingAlert(MjonMsgVO mjonMsgVO) throws Exception {
		JoinSettingVO joinSettingVO = egovSiteManagerService.selectAdminNotiDetail();
		if (joinSettingVO == null || !"Y".equals(joinSettingVO.getHoliSmishingNoti()) || 
			!"Y".equals(joinSettingVO.getSlackNoti())) {
			return false; // 알림 조건 미충족
		}

		// 알림 조건 충족 시 추가 작업
		List<MsgAlarmSetVO> alarmList = getAlarmSettings();
		List<MsgHolidayVO> holidayList = getHolidayList();
		boolean isNotificationAllowed = new MjonHolidayApi().getHolidaySmishingPassStatus(alarmList, holidayList);

		// 알림 발송
		if (!isNotificationAllowed) {
			getAdminSandSlack(mjonMsgVO);
			return true; // 알림 발송 성공
		}

		return false; // 알림 발송 조건 미충족
	}

	// 안전하게 문자열 가져오기
	private String safeGetString(String value) {
		return value == null ? "" : value;
	}

	// 알림 설정 조회
	private List<MsgAlarmSetVO> getAlarmSettings() throws Exception {
		MsgAlarmSetVO msgAlarmSetVO = new MsgAlarmSetVO();
		msgAlarmSetVO.setUseYn("Y");
		msgAlarmSetVO.setFirstIndex(0);
		return msgHolidayService.selectAlarmSettingList(msgAlarmSetVO);
	}

	// 공휴일 정보 조회
	private List<MsgHolidayVO> getHolidayList() throws Exception {
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);

		MsgHolidayVO msgHolidayVO = new MsgHolidayVO();
		msgHolidayVO.setFirstIndex(0);
		msgHolidayVO.setRecordCountPerPage(100);
		msgHolidayVO.setSearchHoliYear(Integer.toString(year));
		return msgHolidayService.selectMsgHolidayList(msgHolidayVO);
	}

	// 이벤트 메시지 처리
	public StatusResponse processEventMessages(String userId, MjonMsgVO mjonMsgVO, 
											List<MjonMsgSendVO> mjonMsgSendVOList) throws Exception {
		StatusResponse statusResponse = new StatusResponse();

		try {
			// 이벤트 정보 가져오기
			MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo_advc(userId);
			if (eventMberInfo == null || "E".equals(eventMberInfo.getEventStatus())) {
				return statusResponse; // 이벤트 상태가 종료인 경우 처리하지 않음
			}

			// 최적화된 메시지 리스트 및 이벤트 정보 가져오기
			OptimalMsgResultDTO result = MsgSendUtils.getOptimalMsgList(eventMberInfo, mjonMsgSendVOList);
			List<MjonMsgSendVO> optimalMsgList = result.getOptimalMsgList();
			MjonEventVO returnEventMberInfo = result.getEventInfo();

			// 이벤트 발송 내역이 있으면
			if (CollectionUtils.isNotEmpty(optimalMsgList)) {
				mjonMsgVO.setEventYn("Y"); // 그룹에 이벤트 발송 여부 설정
				mjonMsgSendVOList.addAll(optimalMsgList); // 기존 리스트와 병합
			}

			// 이벤트 상태 종료 시 업데이트
			if (returnEventMberInfo != null && "E".equals(returnEventMberInfo.getEventStatus())) {
				returnEventMberInfo.setMberId(userId);
				mjonEventService.updateEventEndStatus(returnEventMberInfo);
			}

		} catch (IllegalArgumentException e) {
			
			// 메시지 타입 에러 처리
			MsgSendUtils.statusResponseSet(statusResponse, org.springframework.http.HttpStatus.BAD_REQUEST, "이벤트 데이터 처리 중 오류가 발생하였습니다.\n관리자에게 문의해 주세요.");
			
		}

		return statusResponse;
	}
	
}
