package com.yd.rmi.ali.send.service.impl;


import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.yd.dal.entity.customer.AclCustomer;
import com.yd.dal.entity.sms.ShortMessageSendRecord;
import com.yd.dal.entity.transaction.TransSendList;
import com.yd.dal.service.customer.AclCustomerDALService;
import com.yd.dal.service.transaction.TransSendListService;
import com.yd.rmi.ali.mailinterf.service.AliMailInterfService;
import com.yd.rmi.ali.send.service.SendService;
import com.yd.rmi.ali.sms.service.AliSmsInterfService;
import com.yd.rmi.cache.SystemConfigService;
import com.yd.util.CommonUtil;
import com.yd.util.SpringContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service("sendService")
public class SendServiceImpl implements SendService {

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

	@Autowired
	private AclCustomerDALService aclCustomerService;
	@Autowired
	private TransSendListService transSendListService;
	@Autowired
	private AliSmsInterfService aliSmsInterfService;
	@Autowired
	private AliMailInterfService aliMailInterfService;
	@Autowired
	private SystemConfigService systemConfigService;


	/**
	 * 发送Email和SMS综合接口
	 * @param category 【邮件】填写email，【短信】则填写sms
	 * @param number 【邮箱】--邮箱号，【短信】--手机号
	 * @param type 【邮箱】信件类型【填3】：1-单封邮件发送，2-批量邮件发送，3-SMTP邮件发送，【短信】格式为：1-验证码短信，2-支付提醒短信，3-承保成功短信，4-生日祝福短信，5-续保提现短信，0-临时短信，6-蒙哥方案分析完成短信
	 * @param content 【邮箱】则为邮箱的正文部分，【短信】则为替换短信模板中变量的JSON字符串，如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为  "{\"name\":\""+name+"\",\"code\":\""+code+"\"}";
	 * @param templateCode 【邮箱】--不填，【短信】--短信模板代码
	 * @param subject 【邮箱】--邮箱标题，【短信】--签名信息，最惠比、银盾保险经纪、安吉保、银盾保险在线
	 * @param ccAddress 【邮箱】--抄送的账户，【短信】--不填
	 * @param contentSummary 内容概要
	 * @param useFor 该短信和邮件主要是为了什么发送的，1=订单 2=提现 3=客户意见 4=汽车问卷 5=活动 6=wordPress 7=生日快乐 99=其他'
	 * @param useForId 相应的主键ID，如：订单id等
	 */
	@Override
	@Async("sendAsyncServiceExecutor")
	public void sendEmailOrSMS(String category, String number, String type, String content, String templateCode,
							   String subject, String[] ccAddress, String contentSummary, Integer useFor, Long useForId) {
		int failCount = 0;
		boolean sendResult = false;
		if(CommonUtil.isNullOrBlank(category) || CommonUtil.isNullOrBlank(number) || CommonUtil.isNullOrBlank(type)){
			LOGGER.error("发送类型category不能为空[sms=短信，email=邮件],number、type 都不能为空！");
		}else{
			//获取用户信息
			AclCustomer aclCustomer = getCustomerInfo(category,number);
			//发送email
			if("email".equals(category)){
				if(!CommonUtil.isNullOrBlank(subject) && !CommonUtil.isNullOrBlank(content) ){
					try {
						aliMailInterfService.smtpSend(number,ccAddress, subject, content, null, null);
						sendResult = true;
						LOGGER.info("执行成功！");
					} catch (Exception e) {
						sendResult = false;
						e.printStackTrace();
					}
				}else{
					sendResult = false;
					LOGGER.error("如果发送的是邮件,则subject,content这些信息都不能为空！！！");
				}
				//发送短信
			}else if("sms".equals(category)){
				//如果是非正式环境，校验该手机号码是否可以发送
				boolean isCanSend = canSendForMobile(number);
				if(isCanSend){
					if(!CommonUtil.isNullOrBlank(templateCode)){
						List<String> smsResult = executeSendSMS(number,type,content,templateCode,subject);
//					result = smsResult.get(0);
						failCount = Integer.parseInt(smsResult.get(1));
						sendResult = Boolean.parseBoolean(smsResult.get(2));
						LOGGER.info("执行成功！");
					}else{
						LOGGER.error("如果发送的是邮件,则templateCode(短信模板代码)这些信息都不能为空！！！");
					}
				}
			}else{
				LOGGER.error("该发送类型不存在！category = sms 为短信，category = email 为邮件！");
			}
			//保存结果信息到ag_trans_sendList_temp表中
			saveSendInfo(aclCustomer,category,ccAddress,number,subject,templateCode,useFor,useForId,content,contentSummary,sendResult,failCount);
		}
	}

	@Override
	@Async("sendAsyncServiceExecutor")
	public void sendEmail(String category, String number, String content,
							   String subject, String[] ccAddress, String contentSummary, Integer useFor,List<String> attachmentFiles) {
		int failCount = 0;
		boolean sendResult = false;
		//获取用户信息
		AclCustomer aclCustomer = getCustomerInfo(category, number);
		//发送email
		if ("email".equals(category)) {
			if (!CommonUtil.isNullOrBlank(subject) && !CommonUtil.isNullOrBlank(content)) {
				try {
					aliMailInterfService.smtpSend(number, ccAddress, subject, content, attachmentFiles, null);
					sendResult = true;
					LOGGER.info("执行成功！");
				} catch (Exception e) {
					sendResult = false;
					e.printStackTrace();
				}
			} else {
				LOGGER.error("如果发送的是邮件,则subject,content这些信息都不能为空！！！");
			}
		}
		//保存结果信息到ag_trans_sendList_temp表中
		saveSendInfo(aclCustomer, category, ccAddress, number, subject, null, useFor, null, content, contentSummary, sendResult, failCount);
	}

	@Override
	public boolean sendEmail(String email, String messageText, String subject, String[] ccAddresses) {
		int failCount = 0;
		boolean sendResult = false;
		String category = "email";
		//获取用户信息
		AclCustomer aclCustomer = getCustomerInfo(category, email);
		if (!CommonUtil.isNullOrBlank(subject) && !CommonUtil.isNullOrBlank(messageText)) {
			try {
				aliMailInterfService.smtpSend(email, ccAddresses, subject, messageText, null, null);
				sendResult = true;
				LOGGER.info("执行成功！");
			} catch (Exception e) {
				sendResult = false;
				e.printStackTrace();
			}
		} else {
			LOGGER.error("如果发送的是邮件,则subject,content这些信息都不能为空！！！");
		}
		//保存结果信息到ag_trans_sendList_temp表中
		saveSendInfo(aclCustomer, category, ccAddresses, email, subject, null, 99, null, messageText, "EGolden", sendResult, failCount);
		return sendResult;
	}

	/**
	 * 发送短信
	 * @param mobile 手机号
	 * @param type 格式为：(临时短信一定填"0")0-临时短信，1-验证码短信，2-支付提醒短信，3-承保成功短信，4-生日祝福短信，5-续保提现短信，6-蒙哥方案分析完成短信
	 * @param content 则为替换短信模板中变量的JSON字符串，如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为  "{\"name\":\""+name+"\",\"code\":\""+code+"\"}";
	 * @param templateCode 短信模板代码
	 * @param subject 签名信息，最惠比、银盾保险经纪
	 * @param contentSummary 内容概要
	 * @param useFor 该短信和邮件主要是为了什么发送的，1=订单 2=提现 3=客户意见 4=汽车问卷 5=活动 6=wordPress 7=生日快乐 99=其他'
	 * @param useForId 相应的主键ID，如：订单id等
	 */
	@Override
	@Async("testAsyncServiceExecutor")
	public void sendSMS(String mobile, String type, String content, String templateCode, String subject, String contentSummary, Integer useFor, Long useForId) {
		if(CommonUtil.isNullOrBlank(mobile) || CommonUtil.isNullOrBlank(type) || CommonUtil.isNullOrBlank(templateCode) || useFor == null || useForId == null){
			LOGGER.error("mobile、type、templateCode、useFor、useForId 都不能为空！");
		}else {//根据手机号和邮箱号查询用户的详细信息。
			if (mobile.length() != 11 || !mobile.startsWith("1")) {
				LOGGER.error("手机号码错误！");
			} else {
				AclCustomer customer = getCustomerInfo("sms", mobile);
				if (!CommonUtil.isNullOrBlank(templateCode)) {
					List<String> smsResult = executeSendSMS(mobile, type, content, templateCode, subject);
//					result = smsResult.get(0);
					int failCount = Integer.parseInt(smsResult.get(1));
					boolean sendResult = Boolean.parseBoolean(smsResult.get(2));
					//保存结果信息到ag_trans_sendList_temp表中
					saveSendInfo(customer, "sms", null, mobile, subject, templateCode, useFor, useForId, content, contentSummary, sendResult, failCount);
					LOGGER.info("发送成功！");
				} else {
					LOGGER.error("如果发送的是邮件,则templateCode(短信模板代码)这些信息都不能为空！！！");
				}
			}
		}
	}


	/**
	 * 保存信息进数据库中
	 * @param aclCustomer
	 * @param category
	 * @param ccAddress
	 * @param number
	 * @param subject
	 * @param templateCode
	 * @param useFor
	 * @param useForId
	 * @param content
	 * @param contentSummary
	 * @param sendResult
	 * @param failCount
	 */
	private void saveSendInfo(AclCustomer aclCustomer, String category, String[] ccAddress, String number, String subject, String templateCode, Integer useFor, Long useForId, String content, String contentSummary, boolean sendResult, Integer failCount) {
		//将邮件和短信直接保存到ag_trans_sendList_temp表中
		TransSendList transSendList = new TransSendList();
		transSendList.setSendTag(category);
		transSendList.setSender("zuihuibi");
		if(aclCustomer != null){
			transSendList.setCustomerId(aclCustomer.getId());
			transSendList.setName(aclCustomer.getName());
			if("email".equals(category)){
				transSendList.setMobileNo(aclCustomer.getMobileNo());
			}else{
				transSendList.setEmailTo(aclCustomer.getEmail());
			}
		}
		if("email".equals(category)){
			transSendList.setEmailCc(Arrays.toString(ccAddress) +"");
			transSendList.setEmailTo(number);
			transSendList.setSubject(subject);
		}else{
			transSendList.setMobileNo(number);
			transSendList.setSmsTemplateCode(templateCode);
		}
		transSendList.setUseFor(useFor);
		transSendList.setUseForId(useForId);
		transSendList.setContent(content);
		transSendList.setContentSummary(contentSummary);
		transSendList.setIsSuccess(sendResult ? 1 : 0);
		transSendList.setFailCount(failCount);
		transSendList.setCreatedAt(new Date());
		transSendList.setCreatedBy(-1L);
		transSendList.setUpdatedAt(new Date());
		transSendList.setUpdatedBy(-1L);
		transSendListService.save(transSendList);
	}

	/**
	 * 执行短信发送，如果执行执行4次都失败，则放弃执行
	 * @param number
	 * @param type
	 * @param content
	 * @param templateCode
	 * @param subject
	 * @return
	 */
	private List<String> executeSendSMS(String number, String type, String content, String templateCode, String subject) {
		List<String> resultInfo = new ArrayList<>();
		String result = null;
		int failCount = 0;
		ShortMessageSendRecord smsRecord = new ShortMessageSendRecord();
		smsRecord.setMobileNo(number);
		smsRecord.setSmsType(type);
		smsRecord.setSmsContent(content);
		smsRecord.setTemplateCode(templateCode);
		boolean smsResult = false;
		while (!smsResult && (failCount < 4)){
			SendSmsResponse response =aliSmsInterfService.sendSms(smsRecord,subject);
			result = response.getMessage();
			if ("OK".equals(response.getCode())) {
				smsResult = true;
			}else{
				failCount++;
				System.out.println(">>>>>>>>>>>>第"+failCount+"次失败原因："+response.getMessage());
			}
		}
		resultInfo.add(result);
		resultInfo.add(String.valueOf(failCount));
		resultInfo.add(String.valueOf(smsResult));
		return resultInfo;
	}

	/**
	 * 校验在非正式环境下该手机号码是否能够发送
	 * @param mobileNo
	 * @return
	 */
	private boolean canSendForMobile(String mobileNo) {
		if(!SpringContextUtil.isProd()){
			String mobileNos = systemConfigService.getSingleConfigValue("SMS_TEST_MOBILES");
			if(!mobileNos.isEmpty()){
				List<String> mobileNoList = Arrays.asList(mobileNos.split(","));
				return mobileNoList.contains(mobileNo);//在dev和stage环境只给数据库配置的员工发送短信
			}else{
				return true;
			}
		}else{
			return true;
		}
	}

	/**
	 * 根据类别和手机号码或邮箱，查询用户在系统中的信息
	 * @param category
	 * @param number
	 * @return
	 */
	private AclCustomer getCustomerInfo(String category, String number) {
		AclCustomer aclCustomer = new AclCustomer();
		aclCustomer.setIsActive(1);
		if("email".equals(category)){
			aclCustomer.setEmail(number);
		}else if("sms".equals(category)){
			aclCustomer.setMobileNo(number);
		}
		List<AclCustomer> customerList = aclCustomerService.findByObj(aclCustomer);
		aclCustomer = customerList.isEmpty() ? aclCustomer : customerList.get(0);
		return aclCustomer;
	}


}
