package com.eactive.eai.rms.ext.djb.ums.service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.eactive.apim.portal.common.util.PhoneNumberUtil;
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
import com.eactive.apim.portal.template.entity.MessageRequest;
import com.eactive.eai.common.util.StringUtil;
import com.eactive.eai.common.util.SystemUtil;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.service.MonitoringPropertyService;
import com.eactive.eai.rms.data.entity.onl.apim.messagerequest.MessageRequestService;
import com.eactive.eai.rms.ext.djb.ums.vo.EmailDataVO;
import com.eactive.eai.rms.ext.djb.ums.vo.SmsDataVO;
import com.eactive.eai.rms.ext.djb.ums.vo.StdHeadVO;
import com.eactive.eai.rms.ext.djb.ums.vo.SwingCommonVO;
import com.eactive.eai.rms.ext.djb.ums.vo.SwingDataVO;
import com.eactive.eai.rms.ext.djb.ums.vo.SwingReceiverDataVO;
import com.google.gson.Gson;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class UmsService {
    
    private static final Gson gson = new Gson();

    private static final String SYS_DVCD = "API";		//시스템코드
    private static final String BZWK_DVCD = "99";		//업무구분코드
    private static final String SUB_BZWK_CD = "9019";	//세부구분코드
    private static final String TEAM_DVCD = "00";		//팀구분코드 TODO: 변경해야함
    
    
    private final MonitoringPropertyService propertyService;
    private final MessageRequestService messageRequestService;

    public UmsService(MonitoringPropertyService propertyService, MessageRequestService messageRequestService) {
        this.propertyService = propertyService;
        this.messageRequestService = messageRequestService;
    }

    public boolean send(MessageRequest messageRequest) throws Exception {
        if (messageRequest == null) {
            throw new IllegalArgumentException("messageRequest is null");
        }

        this.httpConnection(messageRequest);

        return true;
    }


    private void httpConnection(MessageRequest messageRequest) throws Exception {
    	HttpURLConnection conn = null;
		BufferedReader br = null;
		log.debug("<<<HTTP Connection>>>:" + messageRequest.toString());
		try {
			String host = propertyService.getPropertyValue("Monitoring", "djb.ums."+messageRequest.getMessageType().toLowerCase()+".url", "");
			
	    	URL url = new URL(host);
	        int timeoutValue = 5 * 1000; // 타임아웃 설정을 위한 값 (단위: ms)
	        // Charset charset = Charset.forName("UTF-8");
			Charset charset = Charset.forName("MS949");
			
			StringBuffer sb = null;
			String bodyData = this.makeBodyData(messageRequest);
			
			String responseData = "";
			String method = bodyData.isEmpty() ? "GET" : "POST";
			conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod(method); // 전송방식
			// conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
			conn.setRequestProperty("Content-Type", "application/json; charset=MS949");
			conn.setConnectTimeout(timeoutValue); // 연결 타임아웃 설정(5초)
			conn.setReadTimeout(timeoutValue); // 읽기 타임아웃 설정(5초)
			conn.setDoOutput(true);
			
			// POst 방식인 경우에만
			if (method.equals("POST")) {
				OutputStream os = conn.getOutputStream();
				byte requestData[] = bodyData.getBytes(charset);
				os.write(requestData);
				os.close();
			}
	
			if (log.isDebugEnabled()) {
				log.debug("getContentType();" + conn.getContentType()); // 응답 콘텐츠 유형 구하기
				log.debug("getResponsecode();" + conn.getResponseCode()); // 응답 코드 구하기
				log.debug("getResponseMessage():" + conn.getResponseMessage()); // 응답 메세지 구하기
	    	}
					
			// http 요청 후 응답 받은 데이타를 버퍼에 쌓는다
			if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
				br = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
			} else {
				br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), charset));
			}
			
			String inputLine;
			sb = new StringBuffer();
			while ((inputLine = br.readLine()) != null) {
				sb.append(inputLine);
			}
			
			responseData = sb.toString();
		} finally {
			// http 요청 및 응답 완료 후 BufferedReader를 닫는다
			if (br != null) {
				br.close();
			}
			if (conn != null) {
				conn.disconnect();
			}
		}
	}
    
    
    
    private String makeBodyData(MessageRequest messageRequest) {
    	// 리턴값
    	String rtnVal = "";
    	
    	// guID 및 날짜 시간 정보
    	String jsonData[] = this.makeStdGuidInfo();
    	
    	// 표준 헤더
    	StdHeadVO stdHeadVO = new StdHeadVO();
    	stdHeadVO.setNxgn_stnd_idfr("JERA");
    	stdHeadVO.setGuid(jsonData[2]);
    	stdHeadVO.setGuid_prgs_no("1");
    	stdHeadVO.setStnd_mesg_ver("R10");
    	stdHeadVO.setOrtr_guid(jsonData[2]);
    	stdHeadVO.setSect_ecrpt_yn("N");
    	stdHeadVO.setFrst_trnm_ipad(propertyService.getPropertyValue("Monitoring", "djb.ums.was_ip_address", ""));
    	stdHeadVO.setFrst_trnm_ipv4_addr(propertyService.getPropertyValue("Monitoring", "djb.ums.was_ip_address", ""));
    	stdHeadVO.setFrst_trnm_mac(propertyService.getPropertyValue("Monitoring", "djb.ums.was_mac_address", ""));
    	stdHeadVO.setFrst_mesg_dman_dt(jsonData[0]);
    	stdHeadVO.setFrst_mesg_dman_time(jsonData[1]);
    	stdHeadVO.setFrst_trnm_sys_dvcd(SYS_DVCD);
    	stdHeadVO.setTrnm_sys_dvcd(SYS_DVCD);
        stdHeadVO.setDman_rspn_dvcd("S"); 								// 요청응답구분코드 S:요청 R:응답
        stdHeadVO.setSys_env_dvcd(SystemUtil.getSysOperEvirnDstcd()); 	// D:개발 T:테스트 P:운영
        stdHeadVO.setTx_tycd("O");										// O:온라인 B:배치
        stdHeadVO.setSynz_dvcd("S");									// S:동기 A:비동기
        stdHeadVO.setChnl_tycd("EAI");									// 채널유형코드 
        stdHeadVO.setHmab_dvcd("1");									// 내외구분코드  1:내부 2:외부(타발)
        stdHeadVO.setIf_id(messageRequest.getEaiInterfaceId());			// 인터페이스ID
        stdHeadVO.setTx_id(messageRequest.getServiceId());				// 거래ID
        
        if ("MESSENGER".equals(messageRequest.getMessageType()) ) {

            stdHeadVO.setChnl_tycd("FEP");								// 채널유형코드 
            
            // 스윙챗 알림 공용
        	SwingCommonVO swiComVO = new SwingCommonVO();
            swiComVO.setClientld(propertyService.getPropertyValue("Monitoring", "djb.ums.messenger.client_id", ""));
        	swiComVO.setClientSecret(propertyService.getPropertyValue("Monitoring", "djb.ums.messenger.client_secret", ""));
        	swiComVO.setCompanyCode("CB");
        	swiComVO.setRequestUniqueKey(this.genrateRandomStringNumber26());
        	
        	// 스윙챗 알림 데이터
        	SwingDataVO swiDataVO = new SwingDataVO();
        	swiDataVO.setNotiCode("CNO_FEP_APIM_0002");	//0001:긴급, 0002:중요
        	swiDataVO.setNotiTitle("알림");
        	swiDataVO.setNotiContent(messageRequest.getMessage());
        	
        	// 스윙챗 알림 데이터
        	List<SwingReceiverDataVO> swiReDataVOList = new ArrayList<SwingReceiverDataVO>();
        	SwingReceiverDataVO receiver = new SwingReceiverDataVO();
        	receiver.setType("PSN");
        	receiver.setCompanyCode("CB");
        	receiver.setCode(messageRequest.getMessengerId());	
        	swiReDataVOList.add(receiver);
        	
        	swiDataVO.setReceiverInfo(swiReDataVOList);
        	
        	String header = gson.toJson(stdHeadVO);
        	String common = gson.toJson(swiComVO);
        	String data = gson.toJson(swiDataVO);
        	
        	// 헤더 + 데이터
        	rtnVal = "{\"HEAD\":" + header + "    ,\r\n" + "\"DATA\":\r\n" + "    [" + "{\r\n"
        				+ "    \"data_dvcd\":\"IO\", \r\n" + "    \"BIZ_DATA\":\r\n" + "    {\r\n"
        				+ "            \"common\":\r\n" + common + ",\r\n" + "      \"data\":" + data
        				+ "    }\r\n" + "         }\r\n" + " ]\r\n" + "}";
        	
    	} 
        else if ("SMS".equals(messageRequest.getMessageType()) 
    			|| "KAKAO".equals(messageRequest.getMessageType())) {
            
            // Sms 데이터
            SmsDataVO dataVO = new SmsDataVO();
            dataVO.setSnd_dman_dt(jsonData[0]);
            dataVO.setSnd_dman_id(this.getSndDmanId(messageRequest.getMessageType()));
            dataVO.setSnd_dvcd("EAI");
            dataVO.setMsg_titl(StringUtil.chunkString(messageRequest.getSubject(), 40, false));	// MS949 40byte 초과시 절단
            dataVO.setMsg_ctnt(messageRequest.getMessage());
            dataVO.setRecvr_no(PhoneNumberUtil.digitsOnly(messageRequest.getPhone()));
            dataVO.setSndn_no("15880079");									//발신번호
            dataVO.setSnd_empno("APIM"); 										//요청자
            dataVO.setSnd_emp_dprm_cd("132"); 									//요청부서코드
            if ("SMS".equals(messageRequest.getMessageType())) {
                dataVO.setLtrs_snd_tycd("1");								// 1:SMS  2:LMS/MMS
            	dataVO.setMsg_snd_tycd("0000"); 							// 알림톡 메세지 종류   0000:SMS, 1000:LMS, 1008:알림톡, ....
            } else if ("KAKAO".equals(messageRequest.getMessageType())) {
                dataVO.setLtrs_snd_tycd("2");								// 1:SMS  2:LMS/MMS
            	dataVO.setMsg_snd_tycd("1008"); 							// 알림톡 메세지 종류   0000:SMS, 1000:LMS, 1008:알림톡, ....
            	//ADMIN으로 시작하면 제주은행 임직원, 나머지는 제주은행 고객용
            	if (messageRequest.getMessageCode().name().startsWith("ADMIN")) {
            		dataVO.setAlmtk_snd_prfl_key(propertyService.getPropertyValue("Monitoring", "djb.ums.sms.almtk_snd_prtl_key.intra", ""));	// 제주은행 임직원 플러스친구아이디 
            	} else {
            		dataVO.setAlmtk_snd_prfl_key(propertyService.getPropertyValue("Monitoring", "djb.ums.sms.almtk_snd_prtl_key.public", ""));	// 제주은행 플러스친구아이디
            	}
            	dataVO.setAlmtk_tmplt_cd(BZWK_DVCD + TEAM_DVCD + SUB_BZWK_CD + "001"); 			// 템플릿코드
            	dataVO.setAlmtk_err_ltrs_snd_yn("Y"); 						// 오류자문자발송여부
            	dataVO.setAlmtk_btn_trnm_tycd("2"); 						// 카카오버튼전송방식  1-format string   2-JSON  3-XML
            }
            dataVO.setSms_trnm_bzwk_dvcd(BZWK_DVCD); 						//업무구분코드
            dataVO.setSms_bzwk_dcls_dvcd(SUB_BZWK_CD);  					//업무세분코드
            dataVO.setSms_sys_dvcd("83"); 									//시스템코드
            dataVO.setTx_dt(jsonData[0]); 									//거래일자
            dataVO.setTx_tktm(jsonData[1].substring(0,6)); 					//거래시간
            
            List<SmsDataVO> dataList = new ArrayList<SmsDataVO>();
            dataList.add(dataVO);
        	
        	String header = gson.toJson(stdHeadVO);
        	String data = gson.toJson(dataList);
        	
        	// 헤더 + 데이터
        	rtnVal = "{\"HEAD\":" + header + "    ,\r\n" + "\"DATA\":\r\n" + "    [" + "{\r\n"
        				+ "    \"data_dvcd\":\"IO\", \r\n" + "    \"BIZ_DATA\":\r\n" + "    {\r\n"
        				+ "            \"ums_if_data_ncnt\":1, \r\n"
        				+ "            \"ums_if_data\":" + data
        				+ "    }\r\n" + "         }\r\n" + " ]\r\n" + "}";
        	
    	} 
        else if ("EMAIL".equals(messageRequest.getMessageType())) {
            
            // 이메일 데이터
            EmailDataVO dataVO = new EmailDataVO();
            dataVO.setUms_evnt_id("");										// TODO: UMS이벤트ID(필수) 
            dataVO.setSnd_dman_dt(jsonData[0]);
            dataVO.setSnd_dman_id("");
            dataVO.setSnd_dman_sno("1");
            dataVO.setEmail_titl(messageRequest.getSubject());				// 메일제목
            dataVO.setCstno("");  											// TODO: 고객번호(필수)
            dataVO.setSendr_emaddr("");  									// TODO: 발신자 이메일
            dataVO.setSendr_nm("");  										// TODO: 발신자 이름
            dataVO.setSndbk_emaddr("");          							// TODO: 리턴 이메일
            dataVO.setRecvr_emaddr(messageRequest.getEmail());				// 수신자 이메일(필수)
            dataVO.setRecvr_nm(messageRequest.getUsername()); 				// 수신자명(필수)
            dataVO.setTmplt_mpng_info(messageRequest.getMessage()); 		// 탬플릿매핑정보
            dataVO.setTmplt_mpng_rptt_info(""); 							// 탬플릿매핑반복정보
            dataVO.setSnd_empno("APIM"); 									// 발신자ID(필수)
            dataVO.setSnd_emp_dprm_cd("132"); 								// 발신자부서코드(필수)
            dataVO.setBzwk_cd(BZWK_DVCD); 									// 업무구분코드
            dataVO.setSub_bzwk_cd(SUB_BZWK_CD); 							// 업무세부코드
            dataVO.setSys_dvcd(SYS_DVCD); 									
            dataVO.setTx_dt(jsonData[0]); 									// 거래일자
            dataVO.setTx_tktm(jsonData[1].substring(0,6)); 					// 거래시간

            List<EmailDataVO> dataList = new ArrayList<EmailDataVO>();
            dataList.add(dataVO);
        	
        	String header = gson.toJson(stdHeadVO);
        	String data = gson.toJson(dataList);
        	
        	// 헤더 + 데이터
        	rtnVal = "{\"HEAD\":" + header + "    ,\r\n" + "\"DATA\":\r\n" + "    [" + "{\r\n"
        				+ "    \"data_dvcd\":\"IO\", \r\n" + "    \"BIZ_DATA\":\r\n" + "    {\r\n"
        				+ "            \"ums_if_data_ncnt\":1, \r\n"
        				+ "            \"ums_if_data\":" + data
        				+ "    }\r\n" + "         }\r\n" + " ]\r\n" + "}";
    	}
    	
    	log.debug(rtnVal);
    	
    	return rtnVal;
    }
    
    
    private String[] makeStdGuidInfo() {
    	// 리턴값
    	String rtnVal[] = new String[3];
    	// 현재시간
    	Date currentDate = new Date();
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    	String formattedDate = sdf.format(currentDate);
    	rtnVal[0] = formattedDate.substring(0,8);
    	rtnVal[1] = formattedDate.substring(8);
    	// 랜던값
    	String random20 = this.genrateRandomStringNumber20();
    	rtnVal[2] = formattedDate  + SYS_DVCD + random20;
    	return rtnVal;
    }
    
    
    private String genrateRandomStringNumber20() {
	    String rtnVal= "";
	    StringBuilder buffer= new StringBuilder(10);
	    // 랜덤값
	    String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	    // 랜덤객체 생성
	    SecureRandom random = new SecureRandom();
	    // 반복문
	    for (int i= 0;i< 10;i++) {
	    	// 랜덤수
	    	int randomIndex = random.nextInt(characters.length());
	    	// 생성된 랜덤값
	    	char randomChar = characters.charAt(randomIndex);
	    	// 랜덤값 저장
	    	buffer.append(randomChar);
	    }
    	// 랜덤객체 재생성
    	random = new SecureRandom();
	    // 난수 10개 생성
	    int random10 = (int) (Math.pow(10, 9) + random.nextDouble() * Math.pow(10, 9));
	    // 문자 숫자 조합(10) + 숫자(10)
	    rtnVal = buffer.toString() + Integer.toString(random10);
	    return rtnVal;
	}
    
    private String genrateRandomStringNumber26() {
		StringBuilder buffer = new StringBuilder(26);
		String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
		SecureRandom random = new SecureRandom();
		for (int i = 0; i < 26; i++) {
			buffer.append(characters.charAt(random.nextInt(characters.length())));
		}
		return buffer.toString();
    }
    
    private String getSndDmanId(String messageType) {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
    	String yyyymmdd = sdf.format(new Date());
    	
    	String uuid = SYS_DVCD + BZWK_DVCD + SUB_BZWK_CD + yyyymmdd + "O" ;
    	
    	if ("SMS".equals(messageType)) {
    		uuid += "S";
    	} else if ("LMS".equals(messageType)) {
    		uuid += "L";
    	} else if ("KAKAO".equals(messageType)) {
    		uuid += "K";
    	}
    	
    	long seq = messageRequestService.countSmsKakaoRequestsOnDate(LocalDate.now()) + 1;
    	uuid += String.format("%014d", seq);

    	return uuid;
    }
}
