package com.style24.core.biz.thirdparty;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.gagaframework.web.parameter.GagaMap;
import com.gagaframework.web.util.GagaStringUtil;
import com.style24.core.biz.dao.NetpathyMailDao;
import com.style24.core.biz.service.TscMailTemplateService;
import com.style24.core.support.env.TscConstants;
import com.style24.persistence.domain.MailTemplate;
import com.style24.persistence.domain.Netpathy;

import lombok.extern.slf4j.Slf4j;

/**
 * 넷퍼시를 이용한 메일 발송
 * 
 * @author gagamel
 * @since 2021. 5. 10
 */
@Component
@Slf4j
public class NetpathyMailSender {

	// 발신자전화번호
	private String callbackTelNo;

	private String domainUrl;

	private String active;

	@Autowired
	private Environment env;

	@Autowired
	private NetpathyMailDao netpathyDao;

	@Autowired
	private TscMailTemplateService mailTemplateService;

	// 메일 답변일련번호
	public enum MailAnswerSq {
		JOIN_CONGRATS(1010),				// 회원가입축하 안내
		TEMP_PASSWD(1011),				// 임시비밀번호발급 안내
		SECEDE_CUST(1012),				// 회원탈퇴 안내
		DORMANT_EXPECT(1013),			// 휴면계정전환예정 안내
		PRIVACY_POLICY(1014),			// 개인정보 이용내역 안내
		MARKETING_AGREE(1015),			// 마케팅 수신동의 안내
		BIRTH_COUPON_NOTICE(1016),		// 생일 축하 안내
		DORMANT_EXPECT_COMBACK(1017),	// 휴면/미접속자방어쿠폰안내
		POINT_EXTNC_EXPECT(1018),		// 포인트 소멸 예정안내

		ORDER_COMPLETE(1019),			// 주문완료 안내
		VA_DEPOSIT_REQUEST(1020),		// 무통장 입금 요청
		CANCEL_REFUND(1021),			// 주문취소 및 환불 안내

		EXCHANGE_REQUEST(1023),			// 교환 접수 안내
		RETURN_REQUEST(1024),			// 반품 접수 안내
		MARKETING_MAIL_1(1025),			// 마케팅메일 1단
		MARKETING_MAIL_2(1026),			// 마케팅메일 2단
		MARKETING_MAIL_3(1027),			// 마케팅메일 3단
		MARKETING_MAIL_MIX(1028),		// 마케팅메일 혼합
		BASIC(1029);						// 기본메일

		private Integer value;

		MailAnswerSq(Integer value) {
			this.value = value;
		}

		public Integer value() {
			return value;
		}
	}

	@PostConstruct
	public void init() {
		domainUrl = env.getProperty("domain.front");
		callbackTelNo = TscConstants.CALLCENTER_TEL_NO;
		active = env.getProperty("spring.profiles.active");

		log.debug("\n\n---- NetpathyMailSender initialization started ----");
		log.debug("domainUrl: [{}]", domainUrl);
		log.debug("callbackTelNo: [{}]", callbackTelNo);
		log.debug("\n--- NetpathyMailSender initialization completed ----\n");
	}

	/**
	 * 메일 발송
	 * @param mailtSq - 메일템플릿번호. 필수
	 * @param toAddress - 보낼 메일 주소. 필수
	 * @param replaceInfo - 메시지내용 중 대체할 정보. 옵션
	 * @author gagamel
	 * @since 2021. 5. 10
	 */
	@Transactional("shopTxnManager")
	public void send(Integer mailtSq, String toAddress, GagaMap replaceInfo) {
		// 2021.08.24 custId 등록작업
		String custId = String.valueOf(replaceInfo.getInt("custNo"));
		this.send(mailtSq, toAddress, replaceInfo, custId);
	}

	/**
	 * 메일 발송
	 * @param mailtSq - 메일템플릿번호. 필수
	 * @param toAddress - 보낼 메일 주소. 필수
	 * @param replaceInfo - 메시지내용 중 대체할 정보. 필수
	 * @param custId - 고객ID. 옵션
	 * @author gagamel
	 * @since 2021. 5. 10
	 */
	@Transactional("shopTxnManager")
	public void send(Integer mailtSq, String toAddress, GagaMap replaceInfo, String custId) {
		// 메일템플릿 조회
		MailTemplate mailTemplate = this.getMailTemplate(mailtSq, replaceInfo);
		StringBuilder contentBuilder = new StringBuilder();
		contentBuilder.append(mailTemplate.getMailhContent());
		contentBuilder.append(mailTemplate.getMailContent());
		contentBuilder.append(mailTemplate.getMailfContent());

		Netpathy netpathy = new Netpathy();
		netpathy.setLegacyid(custId);
		netpathy.setAutotype("ST" + mailtSq);
		netpathy.setEmail(toAddress);
		netpathy.setTitle(mailTemplate.getMailtNm());
		netpathy.setContent(contentBuilder.toString());

		// 메일 생성
		if ("style".equals(active) || "locp".equals(active) || "stage".equals(active) || "brdg".equals(active)) {
			netpathyDao.createMail(netpathy);
		} else {
			netpathyDao.createMailDev(netpathy);
		}

	}

	/**
	 * 메일템플릿 조회
	 * 		어드민의 "회원/마케팅 > 마케팅 > 메일템플릿관리" 화면에서 등록/수정 시 mailTemplate 캐시를 삭제
	 * @param mailtSq - 메일템플릿번호
	 * @param replaceInfo - 메시지내용 중 대체할 정보
	 * @return
	 * @author gagamel
	 * @since 2021. 5. 10
	 */
	@Cacheable(value = "mailTemplate", key = "#mailtSq")
	public MailTemplate getMailTemplate(Integer mailtSq, GagaMap replaceInfo) {
		MailTemplate mailTemplate = mailTemplateService.getMailTemplatePreview(mailtSq);

		mailTemplate.setMailtNm(GagaStringUtil.replace(this.mergeData(mailTemplate.getMailtNm(), replaceInfo), "&gt;", ">"));
		mailTemplate.setMailhContent(GagaStringUtil.replace(this.mergeData(mailTemplate.getMailhContent(), replaceInfo), "&gt;", ">"));
		mailTemplate.setMailfContent(GagaStringUtil.replace(this.mergeData(mailTemplate.getMailfContent(), replaceInfo), "&gt;", ">"));
		mailTemplate.setMailContent(GagaStringUtil.replace(this.mergeData(mailTemplate.getMailContent(), replaceInfo), "&gt;", ">"));

		return mailTemplate;
	}

	/**
	 * 메일내용 조회
	 *
	 * @param mailtSq - 메일템플릿번호
	 * @param replaceInfo - 메시지내용 중 대체할 정보
	 * @return Netpathy
	 * @author jsshin
	 * @since 2021. 07. 16
	 */
	public Netpathy getMailContents(Integer mailtSq, GagaMap replaceInfo) {
		// 메일템플릿 조회
		MailTemplate mailTemplate = this.getMailTemplate(mailtSq, replaceInfo);
		StringBuilder contentBuilder = new StringBuilder();
		contentBuilder.append(mailTemplate.getMailhContent());
		contentBuilder.append(mailTemplate.getMailContent());
		contentBuilder.append(mailTemplate.getMailfContent());

		Netpathy netpathy = new Netpathy();
		netpathy.setAutotype("ST" + mailtSq);
		netpathy.setTitle(mailTemplate.getMailtNm());
		netpathy.setContent(contentBuilder.toString());
		return netpathy;
	}

	/**
	 * 메시지 문자열 중에 '#{'로 시작하고 '}'로 끝나는 부분을 대체할 정보(replaceInfo)로 대체해 반환한다.
	 * @param message - 메시지 문자열
	 * @param replaceInfo - 알림톡 메시지 중 대체할 정보
	 * @return
	 * @author gagamel
	 * @date 2018. 1. 21.
	 */
	private String mergeData(String message, GagaMap replaceInfo) {
		List<String> keyList = getKeyList(message, "#{", "}");

		String key = "";
		String value = "";

		if (!keyList.isEmpty()) {
			for (int i = 0; i < keyList.size(); i++) {
				key = keyList.get(i);
				value = replaceInfo.getString(key);
				message = message.replace("#{" + key + "}", value);
			}
		}

		return message;
	}

	/**
	 * 입력 문자열로부터 시작 태그와 종료 태그 안의 key 목록을 반환한다.
	 * @param inputStr - 입력 문자열
	 * @param startTag - 시작 태그
	 * @param endTag - 종료 태그
	 * @return
	 * @author gagamel
	 * @date 2018. 1. 21.
	 */
	private List<String> getKeyList(String inputStr, String startTag, String endTag) {
		List<String> keyList = new ArrayList<>();

		String targetStr = inputStr;

		while (targetStr.indexOf(startTag) > -1) {
			int startPos = targetStr.indexOf(startTag) + startTag.length();
			int endPos = targetStr.indexOf(endTag, startPos);

			keyList.add(targetStr.substring(startPos, endPos));
			targetStr = targetStr.substring(endPos + endTag.length());
		}

		return keyList;
	}

}
