package com.cftech.mp.reply.service;

import com.alibaba.fastjson.JSONArray;
import com.cftech.accounts.model.MpAccountsEntity;
import com.cftech.core.util.MpTokenUtil;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.mp.api.core.exception.WexinReqException;
import org.mp.api.coupon.qrcode.JwQrcodeAPI;
import org.mp.api.coupon.qrcode.model.GetticketRtn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author 作者 lisw:
 * @version 创建时间：2016年9月7日 下午2:45:04
 *          类说明
 */
@Component
public class WxJsSdkService {


    /**
     * 序列化Redis
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    public boolean init() {
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        //redisTemplate.setValueSerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(stringSerializer);
        return true;
    }

    @SuppressWarnings("rawtypes")
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MpTokenUtil tokenUtil;


    /**
     * @return
     */
    public String getParam(String appid, HttpServletRequest request) {
        try{
            MpAccountsEntity entity =  tokenUtil.searchAccounts(appid);
            String url = getUrl(request);
            Map<String, String> params = sign(tokenUtil.getJSTicket(entity.getId()), url);
            JSONObject jsonObject = JSONObject.fromObject(params);
            String jsonStr = jsonObject.toString();
            System.out.println(jsonStr);
            return jsonStr;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 获取来源URL地址
     *
     * @param request
     * @return
     */
    private static String getUrl(HttpServletRequest request) {
        String url = request.getHeader("Referer");
        return url;
    }

    /**
     * 生成签名
     *
     * @param jsapi_ticket
     * @param url
     * @return
     */
    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String str;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        str = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 生成随机字符串
     *
     * @return
     */
    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    /**
     * 生成时间戳
     *
     * @return
     */
    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }


    /**
     * 微信卡券签名算法
     *
     * @param request lisw 2017-9-12
     * @return
     * @throws WexinReqException
     */
    public String getCardParam(Long accountsId, String openId, String[] cardId, HttpServletRequest request,String outerStr) throws WexinReqException {
        init();
        String redisKey = "api_ticket:" + accountsId;
        String api_ticket = "";
        if (redisTemplate.hasKey(redisKey)) {
            Object api_ticketObj = redisTemplate.opsForValue().get(redisKey);
            if (api_ticketObj != null) {
                api_ticket = api_ticketObj.toString();
            }
        } else {
            GetticketRtn accessToken = JwQrcodeAPI.doGetticket(tokenUtil.getToken(accountsId));
            redisTemplate.opsForValue().set(redisKey, accessToken.getTicket(), 3600, TimeUnit.SECONDS);
            api_ticket = accessToken.getTicket();
        }
        JSONArray array = new JSONArray();
        for(int k=0;k<cardId.length;k++){
            JSONObject obj = new JSONObject();
            Map<String, String> map = new HashMap<String, String>();
            map.put("noncestr", create_nonce_str());
            map.put("timestamp", create_timestamp());
            try{
                //Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }

            map.put("api_ticket", api_ticket);
            map.put("card_id", cardId[k]);
            map.put("code", "");
            map.put("openid", openId);
            String[] str1 = {"openid", "code", "timestamp", "card_id", "api_ticket", "noncestr"};
            String[] valStr = new String[str1.length];
            String url = "";
            for (int i = 0; i < str1.length; i++) {
                valStr[i] = map.get(str1[i]);
            }
            Arrays.sort(valStr);
            for (int j = 0; j < valStr.length; j++) {
                url += valStr[j];
            }
            String signature1 = DigestUtils.shaHex(url);
            obj.put("cardId",cardId[k]);
            JSONObject objExt = new JSONObject();
            StringBuffer json = new StringBuffer();
            json.append("\"{");
            json.append("\"openid\":");
            json.append("\""+openId+"\"");
            json.append(",");
            json.append("\"timestamp\":");
            json.append("\""+map.get("timestamp").toString()+"\"");
            json.append(",");
            json.append("\"signature\":");
            json.append("\""+signature1+"\"");
            json.append(",");
            json.append("\"nonce_str\":");
            json.append("\""+map.get("noncestr").toString()+"\"");
            json.append(",");
            json.append("\"outer_str\":");
            json.append("\""+ outerStr+"\"");
            json.append("}\"");
//            objExt.put("openid",openId);
//            objExt.put("timestamp",map.get("timestamp").toString());
//            objExt.put("signature",signature1);
//            objExt.put("nonce_str",map.get("noncestr").toString());
            obj.put("cardExt", json.toString());
            array.add(obj);
        }
        return array.toString();
    }

}
 