package itn.com.cmm.util;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import itn.let.mail.service.StatusResponse;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msgdata.service.ReplacementListsVO;
import itn.let.module.base.PriceAndPoint;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author 		: 이호영
 * @fileName 	: MsgSendUtils.java 
 * @date 		: 2024.09.23
 * @description : 메세지발송 데이터 다루는 유틸
 * =========================================================== 
 * DATE          AUTHOR   NOTE 
 * ----------------------------------------------------------- *
 * 2024.09.23    이호영          최초 생성
 * 
 * 
 * 
 */
public final class MsgSendUtils {

	
	/** 
	 * @methodName	: getSmsTxtBytes 
	 * @author		: 이호영
	 * @date		: 2024.09.23 
	 * @description	: sms 텍스트 바이트 계산 후 return;
	 * @param smsTxt
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static int getSmsTxtBytes(String smsTxt) throws UnsupportedEncodingException {        	//문자열 길이 체크 해주기
		int smsBytes = 0;
		//문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산
		String charset = "euc-kr"; 						
		if(StringUtils.isNotEmpty(smsTxt)) {
			String smsCont = smsTxt.replace("\r\n", "\n");
			smsBytes = smsCont.getBytes(charset).length;
		}
		return smsBytes;
	}

	/** 
	 * @methodName	: getMsgType 
	 * @author		: 이호영
	 * @date		: 2024.09.23 
	 * @description	: msgType 재정의
	 * @param mjonMsgVO
	 * @param smsTxtByte
	 * @return 
	 */
	public static String getMsgType(MjonMsgVO mjonMsgVO, int smsTxtByte) {
	    String msgType = mjonMsgVO.getMsgType();

	    // 내문자저장함에 저장 후 문자를 발송하는 경우 문자 타입이 숫자가 아닌 문자로 넘어와서 변경 처리함
	    if ("P".equals(msgType) || "L".equals(msgType)) {
	        msgType = "6";
	    } else if ("S".equals(msgType)) {
	        msgType = "4";
	    }

	    // 그림 이미지가 첨부된 경우 장문으로 설정
	    if (mjonMsgVO.getFileName1() != null || (mjonMsgVO.getImgFilePath() != null && mjonMsgVO.getImgFilePath().length > 0)) {
	        msgType = "6";
	    } else if (smsTxtByte > 2000) {
	        // 2000 Byte를 초과할 경우 에러 처리 (이 부분은 호출부에서 검사하도록 유지할 수도 있음)
	        return "INVALID";  // 이 값은 호출부에서 에러 처리를 하도록 활용할 수 있습니다.
	    } else if (smsTxtByte > 90) {
	        // 90Byte 초과 시 장문으로 설정
	        msgType = "6";
	    } else {
	        // 그 외 단문으로 설정
	        msgType = "4";
	    }

	    return msgType;
	}

	public static float getValidPrice(Float personalPrice, Float defaultPrice) {
	    return (personalPrice != null && personalPrice > 0) ? personalPrice : defaultPrice;
	}

	
	/** 
	* @methodName	: determinePriceByMsgType 
	* @author		: 이호영
	* @date		: 2024.09.24 
	* @description	: 문자 메시지 타입에 따라 단가를 결정하는 메서드
	* @param mjonMsgVO
	* @param shortPrice
	* @param longPrice
	* @param picturePrice
	* @param picture2Price
	* @param picture3Price
	* @return 
	*/
	public static float determinePriceByMsgType(MjonMsgVO mjonMsgVO, float shortPrice, float longPrice, 
									float picturePrice, float picture2Price, float picture3Price) {
		float price = 0;
		String msgType = mjonMsgVO.getMsgType();
	
		if ("4".equals(msgType)) {
			price = shortPrice;
		} else if ("6".equals(msgType)) {
			// 파일 첨부 여부에 따라 장문 단가 설정
			if (mjonMsgVO.getFileName3() != null) {
				price = picture3Price;
			} else if (mjonMsgVO.getFileName2() != null) {
				price = picture2Price;
			} else if (mjonMsgVO.getFileName1() != null) {
				price = picturePrice;
			} else {
				price = longPrice;
			}
		}
		return price;
	}

	public static boolean isReplacementRequired(MjonMsgVO mjonMsgVO) {
		return "Y".equals(mjonMsgVO.getTxtReplYn());
	}

	public static ReplacementListsVO createReplacementLists(MjonMsgVO mjonMsgVO) throws UnsupportedEncodingException {
		ReplacementListsVO lists = new ReplacementListsVO();
		lists.initializeLists(mjonMsgVO); // 배열을 초기화합니다.
		return lists;
//		return populateReplacementLists(mjonMsgVO, lists); // 데이터를 배열에 채웁니다.
	}

	/** 
	 * @methodName	: populateReplacementLists 
	 * @author		: 이호영
	 * @date		: 2024.09.26 
	 * @description	: 배열에 데이터를 채우는 메서드 
	 * @param mjonMsgVO
	 * @param lists
	 * @param statusResponse
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static Boolean populateReplacementLists(MjonMsgVO mjonMsgVO, ReplacementListsVO lists, StatusResponse statusResponse){
		
		
		String[] nameList = mjonMsgVO.getNameList();
		String[] phone = mjonMsgVO.getCallToList();
		String[] rep1 = mjonMsgVO.getRep1List();
		String[] rep2 = mjonMsgVO.getRep2List();
		String[] rep3 = mjonMsgVO.getRep3List();
		String[] rep4 = mjonMsgVO.getRep4List();
		String smsTxt = mjonMsgVO.getSmsTxt();
		int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt());
		
		// 이름 치환
		int shortCnt = 0;
		int longCnt = 0;
		int imgCnt = 0;
		
		
		for (int i = 0; i < phone.length; i++) {
			
			smsTxt = smsTxt.replaceAll(String.valueOf((char) 13), "");
			

			// 이름 및 치환 문자 처리
			smsTxt = replacePlaceholder(smsTxt, "[*이름*]", nameList, i);
			smsTxt = replacePlaceholder(smsTxt, "[*1*]", rep1, i);
			smsTxt = replacePlaceholder(smsTxt, "[*2*]", rep2, i);
			smsTxt = replacePlaceholder(smsTxt, "[*3*]", rep3, i);
			smsTxt = replacePlaceholder(smsTxt, "[*4*]", rep4, i);
			

			try {
				int bytes = getSmsTxtBytes(smsTxt);
				if(bytes < 2000) {
					if(fileCount > 0) {
						populateImgLists(lists, nameList, phone, rep1, rep2, rep3, rep4, smsTxt, i);
						imgCnt++;
						
					}else if(bytes > 90) {//장문문자 리스트 만들기
						populateLongLists(lists, nameList, phone, rep1, rep2, rep3, rep4, smsTxt, i);
						longCnt++;
					} else {//단문문자 리스트 만들기
						populateShortLists(lists, nameList, phone, rep1, rep2, rep3, rep4, smsTxt, i);
						shortCnt++;
					}
				}else {
					statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다.");
					return false;
				}
				
			} catch (UnsupportedEncodingException e) {
				statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 중 오류가 발생하였습니다.");
				e.printStackTrace();
				return false;
			}
		}
		
		lists.setShortCnt(shortCnt);
		lists.setLongCnt(longCnt);
		lists.setImgCnt(imgCnt);
		
		return true;

	}
	
	/**
	 * 특정 플레이스홀더를 리스트에서 가져온 값으로 치환합니다.
	 * 
	 * @param smsTxt		문자 내용
	 * @param placeholder	치환할 플레이스홀더 (예: [*이름*])
	 * @param list			치환할 데이터 리스트
	 * @param index			현재 인덱스
	 * @return 치환된 문자 내용
	 */
	private static String replacePlaceholder(String smsTxt, String placeholder, String[] list, int index) {
		if (smsTxt.contains(placeholder)) {
			if (list.length > index && StringUtil.isNotEmpty(list[index])) {
				smsTxt = smsTxt.replaceAll(placeholder, StringUtil.getString(list[index].replaceAll("§", ",")));
			} else {
				smsTxt = smsTxt.replaceAll(placeholder, "");
			}
		}
		return smsTxt;
	}

	private static void populateShortLists(ReplacementListsVO lists, String[] nameList, String[] phone, String[] rep1,
			String[] rep2, String[] rep3, String[] rep4, String smsTxt, int i) {
        // 이름 치환
        if (smsTxt.contains("[*이름*]")) {
            if (nameList.length > i && StringUtil.isNotEmpty(nameList[i])) {
                lists.getShortNameList()[i] = StringUtil.getString(nameList[i].replaceAll("§", ","));
            } else {
                lists.getShortNameList()[i] = " ";
            }
        } else {
            lists.getShortNameList()[i] = getSafeValue(nameList, i);
        }

        lists.getShortPhone()[i] = getSafeValue(phone, i);

        // 문자 1 치환
        if (smsTxt.contains("[*1*]")) {
            lists.getShortRep1()[i] = getReplacementValue(rep1, i, "[*1*]");
        } else {
            lists.getShortRep1()[i] = getSafeValue(rep1, i);
        }

        // 문자 2 치환
        if (smsTxt.contains("[*2*]")) {
            lists.getShortRep2()[i] = getReplacementValue(rep2, i, "[*2*]");
        } else {
            lists.getShortRep2()[i] = getSafeValue(rep2, i);
        }

        // 문자 3 치환
        if (smsTxt.contains("[*3*]")) {
            lists.getShortRep3()[i] = getReplacementValue(rep3, i, "[*3*]");
        } else {
            lists.getShortRep3()[i] = getSafeValue(rep3, i);
        }

        // 문자 4 치환
        if (smsTxt.contains("[*4*]")) {
            lists.getShortRep4()[i] = getReplacementValue(rep4, i, "[*4*]");
        } else {
            lists.getShortRep4()[i] = getSafeValue(rep4, i);
        }
	}

	// 장문 리스트에 데이터를 채우는 메서드
	private static void populateLongLists(ReplacementListsVO lists, String[] nameList, String[] phone, String[] rep1, String[] rep2, String[] rep3, String[] rep4, String smsTxt, int i) {
        // 이름 치환
        if (smsTxt.contains("[*이름*]")) {
            if (nameList.length > i && StringUtil.isNotEmpty(nameList[i])) {
                lists.getLongNameList()[i] = StringUtil.getString(nameList[i].replaceAll("§", ","));
            } else {
                lists.getLongNameList()[i] = " ";
            }
        } else {
            lists.getLongNameList()[i] = getSafeValue(nameList, i);
        }

        lists.getLongPhone()[i] = getSafeValue(phone, i);

        // 문자 1 치환
        if (smsTxt.contains("[*1*]")) {
            lists.getLongRep1()[i] = getReplacementValue(rep1, i, "[*1*]");
        } else {
            lists.getLongRep1()[i] = getSafeValue(rep1, i);
        }

        // 문자 2 치환
        if (smsTxt.contains("[*2*]")) {
            lists.getLongRep2()[i] = getReplacementValue(rep2, i, "[*2*]");
        } else {
            lists.getLongRep2()[i] = getSafeValue(rep2, i);
        }

        // 문자 3 치환
        if (smsTxt.contains("[*3*]")) {
            lists.getLongRep3()[i] = getReplacementValue(rep3, i, "[*3*]");
        } else {
            lists.getLongRep3()[i] = getSafeValue(rep3, i);
        }

        // 문자 4 치환
        if (smsTxt.contains("[*4*]")) {
            lists.getLongRep4()[i] = getReplacementValue(rep4, i, "[*4*]");
        } else {
            lists.getLongRep4()[i] = getSafeValue(rep4, i);
        }
	}

	// 그림 문자 리스트에 데이터를 채우는 메서드
	private static void populateImgLists(ReplacementListsVO lists, String[] nameList, String[] phone, String[] rep1, String[] rep2, String[] rep3, String[] rep4, String smsTxt, int i) {
		
		// 이름 치환
		if (smsTxt.contains("[*이름*]")) {
		    if (nameList.length > i && StringUtil.isNotEmpty(nameList[i])) {
		        lists.getImgNameList()[i] = StringUtil.getString(nameList[i].replaceAll("§", ","));
		    } else {
		        lists.getImgNameList()[i] = " ";
		    }
		} else {
		    lists.getImgNameList()[i] = getSafeValue(nameList, i);
		}
		
		lists.getImgPhone()[i] = getSafeValue(phone, i);
		
		// 문자 1 치환
		if (smsTxt.contains("[*1*]")) {
		    lists.getImgRep1()[i] = getReplacementValue(rep1, i, "[*1*]");
		} else {
		    lists.getImgRep1()[i] = getSafeValue(rep1, i);
		}
		
		// 문자 2 치환
		if (smsTxt.contains("[*2*]")) {
		    lists.getImgRep2()[i] = getReplacementValue(rep2, i, "[*2*]");
		} else {
		    lists.getImgRep2()[i] = getSafeValue(rep2, i);
		}
		
		// 문자 3 치환
		if (smsTxt.contains("[*3*]")) {
		    lists.getImgRep3()[i] = getReplacementValue(rep3, i, "[*3*]");
		} else {
		    lists.getImgRep3()[i] = getSafeValue(rep3, i);
		}
		
		// 문자 4 치환
		if (smsTxt.contains("[*4*]")) {
		    lists.getImgRep4()[i] = getReplacementValue(rep4, i, "[*4*]");
		} else {
		    lists.getImgRep4()[i] = getSafeValue(rep4, i);
		}
		
	}

	// 배열 인덱스를 안전하게 접근하는 메서드
	private static String getSafeValue(String[] array, int index) {
	    return (array != null && array.length > index) ? array[index] : " ";
	}

	// 치환 처리에 특수문자 제거 로직이 포함된 메서드
	private static String getReplacementValue(String[] array, int index, String placeholder) {
	    if (array != null && array.length > index && StringUtil.isNotEmpty(array[index])) {
	        return StringUtil.getString(array[index].replaceAll("§", ","));
	    } else {
	        return " ";
	    }
	}
	
	

	private static void statusResponseSet (StatusResponse statusResponse, HttpStatus httpStatus, String msg ) {
		statusResponse.setStatus(httpStatus);
		statusResponse.setMessage(msg);
		
	}

	public static StatusResponse validateFilesForMessageSending(int fileCount, MjonMsgVO mjonMsgVO) {
		if (fileCount > 0) {
			boolean allFilesAreNull = Stream
					.of(mjonMsgVO.getFileName1(), mjonMsgVO.getFileName2(), mjonMsgVO.getFileName3())
					.allMatch(Objects::isNull);

			if (allFilesAreNull) {
				return new StatusResponse(HttpStatus.NO_CONTENT, "문자 메세지 이미지 추가에 오류가 발생하여 문자 발송이 취소 되었습니다.");
			}
		}
		return null; // 유효성 검사를 통과한 경우
	}


	/** 
	 * @methodName	: validateReplacementData 
	 * @author		: 이호영
	 * @date		: 2024.09.25
	 * @description	: 치환문자가 사용될 때 데이터가 올바른지 확인하는 메서드
	 * @param mjonMsgVO
	 * @param statusResponse
	 * @return boolean
	 */
	public static boolean validateReplacementData(MjonMsgVO mjonMsgVO, StatusResponse statusResponse) {
		String[] nameList = mjonMsgVO.getNameList();
		String[] phone = mjonMsgVO.getCallToList();
		String[] rep1 = mjonMsgVO.getRep1List();
		String[] rep2 = mjonMsgVO.getRep2List();
		String[] rep3 = mjonMsgVO.getRep3List();
		String[] rep4 = mjonMsgVO.getRep4List();

		// 치환 문자 리스트가 모두 비어있는지 확인
		if (isEmpty(nameList) 
			&& isEmpty(rep1) 
			&& isEmpty(rep2) 
			&& isEmpty(rep3) 
			&& isEmpty(rep4)) {
			statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "특정문구 일괄변환 치환문자 데이터가 없습니다.");
			return false;
		}

		// 치환 문자 필드 개수와 전화번호 개수가 일치하는지 확인
		boolean isRepCountOk = true;

		if (mjonMsgVO.getSmsTxt().contains("[*이름*]") && nameList.length != phone.length) {
			isRepCountOk = false;
		}
		if (mjonMsgVO.getSmsTxt().contains("[*1*]") && rep1.length != phone.length) {
			isRepCountOk = false;
		}
		if (mjonMsgVO.getSmsTxt().contains("[*2*]") && rep2.length != phone.length) {
			isRepCountOk = false;
		}
		if (mjonMsgVO.getSmsTxt().contains("[*3*]") && rep3.length != phone.length) {
			isRepCountOk = false;
		}
		if (mjonMsgVO.getSmsTxt().contains("[*4*]") && rep4.length != phone.length) {
			isRepCountOk = false;
		}

		// 필드 개수가 일치하지 않는 경우 에러 메시지 반환
		if (!isRepCountOk) {
			statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "특정문구 일괄변환 치환문자 데이터가 일치하지 않습니다.");
			return false;
		}

		return true; // 모든 유효성 검사를 통과한 경우
	}
	
	// 배열이 비어있는지 확인하는 메서드
	public static boolean isEmpty(String[] array) {
		return array == null || array.length == 0;
	}

	
}
