package cn.hmsoft.hmplatform.wxtoken.util;

import java.time.LocalDateTime;

import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.helper.BeanHelper;
import cn.hmsoft.helper.LocalDateHelper;
import cn.hmsoft.helper.LocalDateHelper.LocalDateCompareType;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDefineDao;
import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenRequest;
import cn.hmsoft.log.LogHelper;
import cn.hmsoft.weixin.data.model.WxDefine;
import cn.hmsoft.weixin.entity.response.TicketResponseJson;
import cn.hmsoft.weixin.entity.response.TokenResponseJson;
import cn.hmsoft.weixin.request.TicketGetRequest;
import cn.hmsoft.weixin.request.TokenRequest;
import cn.hmsoft.weixin.util.WeiXinParamUtil;

/*************************
 * 获取线程token
 *
 */
public class WeixinTokenRequestThread extends Thread {

	private PWxDefine wx;
	private PWxDefineDao daoDefine;
	private boolean requesting = false;
	private LocalDateTime requestTime = null;

	public WeixinTokenRequestThread(PWxDefine wx) {
		this.wx = wx;
		this.daoDefine = SpringHelper.getBean(PWxDefineDao.class);
	}

	@Override
	public void run() {
		while (true) {
			this.checkToken();
		}
	}

	/*********************************
	 * 获取token
	 */
	private void checkToken() {

		if (this.wx.getApp_token_expired() != null && this.wx.getApp_token_expired().isAfter(LocalDateTime.now())) {
			try {
				Thread.sleep(LocalDateHelper.calTimeDiff(wx.getApp_token_expired(), LocalDateTime.now(),
						LocalDateCompareType.Millis));
			} catch (Exception e) {

			}
		}
		try {
			// 重新获取密钥，防止在这之间更改过密钥
			PWxDefine p = this.daoDefine.findWxDefine(this.wx.getApp_id());
			if (p != null)
				this.wx.setApp_secrect(p.getApp_secrect());
			fetchToken();
		} catch (Exception e) {
			LogHelper.error(e);
		}
		if (this.wx.getApp_token_expired() == null || this.wx.getApp_token_expired().isBefore(LocalDateTime.now())) {
			// 获取失败
			try {
				Thread.sleep(WeiXinParamUtil.TokenWaitSeconds * 3 * 1000);
			} catch (Exception e) {

			}
		}
	}

	private void fetchToken() {
		requesting = true;
		TokenRequest rq = new TokenRequest();
		WxDefine token = BeanHelper.copy(WxDefine.class, this.wx);
		rq.setWxDefine(token);
		TokenResponseJson response = null;
		int requestTotal = 0;
		requestTime = LocalDateTime.now();
		String msg = "";
		do {
			try {
				response = rq.request();
			} catch (Exception e) {
				msg = msg + "\n" + (requestTotal + 1) + ":" + e.getMessage();
				response = null;
			}
			if (response != null) {
				break;
			}
			// 没有返回，网络错误，重试
			try {
				Thread.sleep(WeiXinParamUtil.TokenIntervalSeconds * 1000);
			} catch (Exception e) {
			}
			requestTotal++;
		} while (response == null && requestTotal < WeiXinParamUtil.TokenRetryTimes);

		this.recoredRequestToken(response);
		if (response == null) {
			LogHelper.error(
					"------ Token获取失败，[" + this.wx.getWx_name() + "][" + this.wx.getApp_id() + "]-" + msg + "-----");
			requesting = false;
			return;
		} else {
			if (StringHelper.isNotEmpty(response.getAccess_token())) {
				LogHelper.info("------ [" + this.wx.getWx_name() + "] Token获取成功------");
			} else {
				LogHelper.error("------ Token获取失败，[" + this.wx.getWx_name() + "][" + this.wx.getApp_id() + "]，["
						+ response.getErrmsg() + "]------");
				requesting = false;
				return;
			}
		}

		// 取ticket
		TicketGetRequest ticketRequest = new TicketGetRequest();
		ticketRequest.setWxDefine(token);
		TicketResponseJson ticketResponse = null;
		requestTotal = 0;
		do {
			try {
				ticketResponse = ticketRequest.request();
			} catch (Exception e) {
				ticketResponse = null;
			}
			if (ticketResponse != null && StringHelper.isNotEmpty(ticketResponse.getTicket())) {
				break;
			}
			try {
				Thread.sleep(WeiXinParamUtil.TokenIntervalSeconds * 1000);
			} catch (Exception e) {

			}
			ticketResponse = null;
			requestTotal++;
		} while (ticketResponse == null && requestTotal < WeiXinParamUtil.TokenRetryTimes);
		if (ticketResponse == null) {
			LogHelper.error("------ jsapi获取失败，[" + this.wx.getApp_id() + "]------");
			requesting = false;
			// return;
		}

		try {
			// 写入数据库
			this.daoDefine.updateBySql(
					"update p_wx_define set app_accesstoken=?,app_token_expired=?,app_jsapi=?,app_token_time=? where app_id=?",
					token.getApp_accesstoken(), token.getApp_token_expired(), token.getApp_jsapi(), LocalDateTime.now(),
					token.getApp_id());
			this.wx.setApp_accesstoken(token.getApp_accesstoken());
			this.wx.setApp_token_expired(token.getApp_token_expired());
			this.wx.setApp_jsapi(token.getApp_jsapi());
		} catch (Exception e) {
			LogHelper.error(e);
		}

		this.requesting = false;
		// 推送线程
		new Thread(new WeixinTokenNoticeThread(wx)).start();
	}

	private void recoredRequestToken(TokenResponseJson response) {
		// 记录日志

		PWxTokenRequest log = new PWxTokenRequest();
		log.setToken_id(this.wx.getToken_id());
		log.setApp_accesstoken(this.wx.getApp_accesstoken());
		log.setApp_accesstokenkey(this.wx.getApp_accesstokenkey());
		log.setApp_jsapi(this.wx.getApp_jsapi());
		log.setApp_token_expired(this.wx.getApp_token_expired());
		log.setRequest_time(requestTime);
		log.setResponse_time(LocalDateTime.now());
		log.setError_code(response == null ? "-1" : (response.getErrcode() + ""));
		log.setError_msg(response == null ? "无法访问微信服务器" : response.getErrmsg());
		try {
			this.daoDefine.insert(log);
		} catch (Exception e) {
			LogHelper.error(e);
		}
	}

	public PWxDefine getWxDefine() {
		while (this.requesting == true) {
			try {
				Thread.sleep(1000);
			} catch (Exception e) {

			}
		}
		return this.wx;
	}
}
