package com.wechat.common;

import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.wechat.activerequests.responses.MessageIdResponse;
import com.wechat.common.utils.AESUtil;
import com.wechat.common.utils.JacksonUtils;
import com.wechat.common.utils.MessageUtils;
import com.wechat.common.utils.NetworkUtils;
import com.wechat.common.utils.NumberUtils;
import com.wechat.common.utils.StringsUtils;
import com.wechat.model.dbEntity.MdeLoginHis;
import com.wechat.model.requestDto.TMsgSendBaseReq;
import com.wechat.service.WeiXinService;

import nl.basjes.parse.useragent.UserAgent;
import nl.basjes.parse.useragent.UserAgentAnalyzer;


/**
 * The common method shared in all project
 * 
 * @author Administrator
 */
@Component
public class CommonHelper {
	// url根目录
	@Value("#{configProperties['hostPort']}")
	private String urlBase;

	// 模板消息发送用url
	@Value("#{configProperties['weixin.tmsg.send']}")
	private String tmsgSendUrl;

	// token过期时间
	@Value("#{configProperties['token.expire.minute']}")
	private String tokenExpireTime;

	private static final Log log = LogFactory.getLog(CommonHelper.class);

	public String getIRealIPAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip) || "null".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip) || "null".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip) || "null".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}

		// 如果通过多级反向代理，X-Forwarded-For的值不止一个，而是一串用逗号分隔的IP值，此时取X-Forwarded-For中第一个非unknown的有效IP字符串
		if ((ip.indexOf(",") > -1)) {
			ip = ip.split(",")[0];
		}
		return ip;
	}

	/**
	 * 验证是否是手机号码
	 * 
	 * @param mobile
	 * @return
	 */
	public boolean isMobile(String mobile) {
		Pattern p = null;
		Matcher m = null;
		p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$"); // 验证手机号
		m = p.matcher(mobile);
		return m.matches();
	}

	/**
	 * 取得完整的图片访问url
	 * 
	 * @param mobile
	 * @return
	 */
	public String getImgUrl(String urlChild) {
		return urlBase + urlChild;
	}

	/**
	 * 模板消息推送
	 * 
	 * @param keyWord
	 *            用户发送的信息
	 * @return
	 */
	public String send(TMsgSendBaseReq req) {
		String url = MessageUtils.getText(tmsgSendUrl, WeiXinService.getInstance().getAccessToken());
		MessageIdResponse response = NetworkUtils.getRemoteResponseAsJson(url, req, MessageIdResponse.class);
		log.debug("Responded: " + JacksonUtils.beautifulSerialize(response));

		// 模板消息推送出错
		if (!StringsUtils.isEqual(Constants.STR_OK, Long.toString(response.getErrorCode()))) {
			log.error("模板消息推送异常：ErrorMsg=" + response.getErrorMsg() + "; ErrorCode=" + response.getErrorCode()
					+ "; MessageId=" + response.getMessageId());
			// 40001 的情况下强制重取token
			if (StringsUtils.isEqual(Constants.STR_TOKEN_ERO, Long.toString(response.getErrorCode()))) {
				WeiXinService.getInstance().updAccessTokenInfo();
				url = MessageUtils.getText(tmsgSendUrl, WeiXinService.getInstance().getAccessToken());
			}
			// 重新发送
			response = NetworkUtils.getRemoteResponseAsJson(url, req, MessageIdResponse.class);
			log.error("模板消息重发：ErrorMsg=" + response.getErrorMsg() + "; ErrorCode=" + response.getErrorCode()
					+ "; MessageId=" + response.getMessageId());
		}

		return response.getErrorCode().toString();
	}

	/**
	 * token生成
	 * 
	 * @param userCode 用户code          
	 * @param req
	 * @param identityFlag 个人企业区分
	 * @param creatDate    用户注册日期
	 * @return
	 * @throws IllegalArgumentException
	 * @throws JWTCreationException
	 * @throws UnsupportedEncodingException
	 */
	public String getToken(String userCode, String identityFlag, String creatDate)
			throws IllegalArgumentException, JWTCreationException, UnsupportedEncodingException {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, NumberUtils.stringToInt(tokenExpireTime, 120));
		// 生成token 用户code拼上随机字符串进行md5加密
		String token = JWT.create().withClaim(Constants.TOKEN_USER_ID, userCode).withClaim(Constants.TOKEN_IDENTITY_FLAG, identityFlag).withClaim(Constants.TOKEN_CREATDATE, creatDate).withExpiresAt(calendar.getTime())
				.sign(Algorithm.HMAC512(Constants.TOKEN_KEY));
		return token;
	}

	/**
	 * ActivationToken生成 邮箱激活token
	 * 
	 * @param userCode
	 *            用户code
	 * @return token
	 * @throws UnsupportedEncodingException
	 * @throws JWTCreationException
	 * @throws IllegalArgumentException
	 */
	public String getActivationToken(String userCode)
			throws IllegalArgumentException, JWTCreationException, UnsupportedEncodingException {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_YEAR, 5);
		// 生成token 用户code拼上随机字符串进行md5加密
		String token = JWT.create().withClaim(Constants.ACTIVATION_TOKEN, userCode).withExpiresAt(calendar.getTime())
				.sign(Algorithm.HMAC512(Constants.TOKEN_KEY));
		return token;
	}
	
	
	/**
	 * 获取客户端信息
	 * @param request
	 * @return
	 */
	public MdeLoginHis getDeviceType(HttpServletRequest request) {
		MdeLoginHis his = new MdeLoginHis();
        String agentString = request.getHeader("User-Agent");
        
        UserAgentAnalyzer a = UserAgentAnalyzer.newBuilder().hideMatcherLoadStats().delayInitialization().build();
        UserAgent userAgent = a.parse(agentString);

        // 浏览器信息
        his.setBrowser(userAgent.getValue(UserAgent.AGENT_NAME));
        his.setBrowserVersion(userAgent.getValue(UserAgent.AGENT_NAME_VERSION));
        his.setIp(getIRealIPAddr(request));
        // 设备信息
        String deviceName = userAgent.getValue(UserAgent.DEVICE_NAME);

    	String lower = agentString.toLowerCase();
    	if(lower.contains("devtool") || lower.contains("postman") || lower.contains("request") || lower.contains("debug") || lower.contains("api")) {
    		deviceName = "IT人员！";
    	}
        his.setOperating(deviceName);
        
        // 设备类型
        his.setDeviceClass(userAgent.getValue(UserAgent.DEVICE_CLASS));
    	
    	// 操作系统信息
        his.setSystem(userAgent.getValue(UserAgent.OPERATING_SYSTEM_NAME_VERSION));
      
        his.setRemarks(agentString);

        return his;
    }
	
	/**
	 * 根据shareJob 获取jobid
	 * @param request
	 * @return
	 */
	public int getJobId(String shareJob) {
		String jobId = shareJob.substring(10);
        return NumberUtils.stringToInt(jobId, 0);
    }
	
	
	
	/**
	 * 获取分享用-用户code
	 * Aes加密
	 * @param request
	 * @return
	 */
	public String getShareCodeAes(String userCode, Date creatTime) {
		String shareCode = AESUtil.encrypt(userCode+Constants.UNDER_LINE+String.valueOf(creatTime.getTime()), Constants.AES_PASSWORD);
        return shareCode;
    }
	
	/**
	 * 获取分享用-用户code
	 * Aes解密
	 * @param request
	 * @return
	 */
	public String[] getUserCodeAes(String shareCode) {
		/*
		 * try { shareCode = URLDecoder.decode(shareCode,"utf-8"); } catch
		 * (UnsupportedEncodingException e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); }
		 */
		String shareCodeStr = AESUtil.decryptStr(shareCode, Constants.AES_PASSWORD);
        return shareCodeStr.split(Constants.UNDER_LINE);
    }

}
