package com.ghy.web.controller.tool;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.config.WxConfig;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.enums.OrderStatus;
import com.ghy.common.exception.ServiceException;
import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.StringUtils;
import com.ghy.common.utils.WechatMsgUtils;
import com.ghy.common.utils.WxUtils;
import com.ghy.common.utils.http.HttpUtils;
import com.ghy.customer.domain.Customer;
import com.ghy.customer.service.CustomerService;
import com.ghy.system.domain.NoticeMsg;
import com.ghy.system.domain.SysDeptConfig;
import com.ghy.system.service.ISysDeptConfigService;
import com.ghy.system.service.IWxMsgService;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.service.WorkerService;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author clunt
 * 微信通用请求接口
 */
@Controller
@RequestMapping("/wx")
@CrossOrigin(origins = "*", maxAge = 3600)
public class WxController extends BaseController {

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    private ISysDeptConfigService sysDeptConfigService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private WorkerService workerService;

    @Autowired
    private IWxMsgService wxMsgService;

    @PostMapping("/noticeMsg")
    @ResponseBody
    public AjaxResult noticeMsg(@RequestBody NoticeMsg noticeMsg){
        try {
            wxMsgService.sendMsg(noticeMsg.getOpenId(), noticeMsg.getRemind(),
                    noticeMsg.getOrderId(), noticeMsg.getName(), OrderStatus.valueOf(noticeMsg.getOrderStatus()),
                    System.currentTimeMillis());
            return AjaxResult.success();
        }catch (Exception e){
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error(e.getMessage());
        }
    }

    @PostMapping("/addUser")
    @ResponseBody
    public AjaxResult addUser(@RequestBody Customer customer){
        try {
            int result = customerService.insertCustomer(customer);
            if(result>0){
                return AjaxResult.success("新增用户成功");
            }else {
                return AjaxResult.warn("新增用户失败!");
            }
        }catch (Exception e){
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error(e.getMessage());
        }
    }

    @PostMapping("/getUserInfo")
    @ResponseBody
    public AjaxResult getUserInfo(@RequestBody Customer customer){
        try {
            return AjaxResult.success(customerService.selectByOpenId(customer));
        }catch (Exception e){
            return AjaxResult.error(e.getMessage());
        }
    }

    @PostMapping("/addWorker")
    @ResponseBody
    public AjaxResult addUser(@RequestBody Worker worker){
        try {
            int result = workerService.insertWorker(worker);
            if(result>0){
                return AjaxResult.success("新增师傅成功");
            }else {
                return AjaxResult.warn("新增师傅失败!");
            }
        }catch (Exception e){
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error(e.getMessage());
        }
    }

    @PostMapping("/getWorkerInfo")
    @ResponseBody
    public AjaxResult getUserInfo(@RequestBody Worker worker){
        try {
            return AjaxResult.success(workerService.selectByOpenId(worker));
        }catch (Exception e){
            return AjaxResult.error(e.getMessage());
        }
    }

    @GetMapping("/token")
    @ResponseBody
    public String token(String timestamp, String nonce, String signature, String echostr) throws IOException {
        String token = "gqz";
        boolean checkSignature = checkSignature(signature, timestamp, nonce, token);
        if (checkSignature) {
            return echostr;
        } else {
            return null;
        }
    }

    @GetMapping("/token/code")
    @ResponseBody
    public JSONObject tokenCode(HttpServletRequest request) throws IOException{
        JSONObject wxUser = WxUtils.getOpenid(request.getParameter("code"), "wx404f2439a8c24e15", "49ade04a817067fe2d65ab2f17afce75");
        String openId = wxUser.getString("openid");
        if(StringUtils.isNotEmpty(openId)){
            String questionUrl = "https://www.opsoul.com:8883/exam/question/details/list/";
            JSONObject result = new JSONObject();
            result.put("data", HttpUtils.sendGet(questionUrl + openId));
            result.put("openid", openId);
            return result;
        }else {
            return null;
        }
    }

    @GetMapping("/auth/phone")
    @ResponseBody
    public AjaxResult authPhone(HttpServletRequest request){
        try {
            String code = request.getHeader("code");
            String from = request.getHeader("from");
            String deptId = request.getHeader("deptId");
            SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
            String accessToken;
            if("customer".equals(from)){
                accessToken = getAccessToken(sysDeptConfig.getWxAppId(), sysDeptConfig.getWxSecret());
            }else {
                accessToken = getAccessToken(sysDeptConfig.getServWxAppId(), sysDeptConfig.getServWxSecret());
            }
            return AjaxResult.success("获取手机号成功", getPhoneNumber(code, accessToken));
        }catch (Exception e){
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error(e.getMessage());
        }
    }

    @GetMapping("/auth")
    @ResponseBody
    public AjaxResult auth(HttpServletRequest request) {
        String url;
        String deptId = request.getHeader("deptId");
        String from = request.getHeader("from");
        SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
        String code = request.getHeader("code");
        if("customer".equals(from)){
            url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getWxAppId() + "&secret=" + sysDeptConfig.getWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        }else {
            url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getServWxAppId() + "&secret=" + sysDeptConfig.getServWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        }
        String data = HttpUtils.sendGet(url, null);
        JSONObject result = JSONObject.parseObject(data);
        // 如果是师傅端,需要调用公众号的获取用户列表接口 -- 遍历列表去找到unionId和openid关联并入库
//        if(!"customer".equals(from)){
//            String openid = result.getString("openid");
//            String unionId = result.getString("unionid");
//            // 查询openid是否入库，已经入库则不管
//            Worker param = new Worker();
//            param.setOpenId(openid);
//            Worker worker = workerService.selectByOpenId(param);
//            if(worker != null && StringUtils.isEmpty(worker.getWxOpenId())){
//                // 公众号token
//                String wxToken = WechatMsgUtils.getToken();
//                String wxUserOpenidList = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+wxToken+"&next_openid=");
//                logger.info("公众号获取的用户列表集合:{}", wxUserOpenidList);
//                JSONObject wxOpenidJson = JSONObject.parseObject(wxUserOpenidList);
//                JSONObject openIdListJson = wxOpenidJson.getJSONObject("data");
//                List<String> openidList = openIdListJson.getObject("openid", ArrayList.class);
//                JSONArray openidJsonArray = new JSONArray();
//                openidList.forEach(model->{
//                    JSONObject openidJson = new JSONObject();
//                    openidJson.put("openid", model);
//                    openidJson.put("lang", "zh_CN");
//                    openidJsonArray.add(openidJson);
//                });
//                JSONObject jsonParam = new JSONObject();
//             xw   jsonParam.put("user_list", openidJsonArray);
//                String unionUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="+WechatMsgUtils.getToken();;
//                logger.info("调用获取用户信息,请求url:{}, 请求body:{}", unionUrl, jsonParam.toJSONString());
//                String getUnionResult = HttpUtil.post(unionUrl, jsonParam.toJSONString());
//                logger.info("获取公众号union列表:{}", getUnionResult);
//                JSONObject unionJson = JSONObject.parseObject(getUnionResult);
//                JSONArray unionJsonArray = unionJson.getJSONArray("user_info_list");
//                for (int index = 0 ; index<unionJsonArray.size(); index ++){
//                    JSONObject json = unionJsonArray.getJSONObject(index);
//                    if(StringUtils.isEmpty(json.getString("unionid"))||StringUtils.isEmpty(unionId)){
//                        return AjaxResult.success(result);
//                    }
//                    if(json.getString("unionid").equals(unionId)){
//                        Worker updateWorker = new Worker();
//                        updateWorker.setWorkerId(worker.getWorkerId());
//                        updateWorker.setWxOpenId(json.getString("openid"));
//                        logger.info("关联后的worker信息:{}", worker);
//                        workerService.updateWorker(updateWorker);
//                    }
//                }
//            }
//
//        }
        return AjaxResult.success(result);
    }

    @GetMapping("/check")
    @ResponseBody
    public AjaxResult check(HttpServletRequest request) {
        String url;
        boolean flag = false;
        String deptId = request.getHeader("deptId");
        String from = request.getHeader("from");
        SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
        String code = request.getHeader("code");
        if("customer".equals(from)){
            url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getWxAppId() + "&secret=" + sysDeptConfig.getWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        }else {
            url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getServWxAppId() + "&secret=" + sysDeptConfig.getServWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        }
        String data = HttpUtils.sendGet(url, null);
        JSONObject result = JSONObject.parseObject(data);
        // 如果是师傅端,需要调用公众号的获取用户列表接口 -- 遍历列表去找到unionId和openid关联并入库
        if(!"customer".equals(from)){
            String openid = result.getString("openid");
            String unionId = result.getString("unionid");
            // 查询openid是否入库，已经入库则不管
            Worker param = new Worker();
            param.setOpenId(openid);
            Worker worker = workerService.selectByOpenId(param);
            if(worker != null){
                // 公众号token
                String wxToken = WechatMsgUtils.getToken();
                String wxUserOpenidList = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+wxToken+"&next_openid=");
                logger.info("公众号获取的用户列表集合:{}", wxUserOpenidList);
                JSONObject wxOpenidJson = JSONObject.parseObject(wxUserOpenidList);
                JSONObject openIdListJson = wxOpenidJson.getJSONObject("data");
                List<String> openidList = openIdListJson.getObject("openid", ArrayList.class);
                List<List<String>> batchList = ListUtil.partition(openidList, 99);
                for (List<String> childOpenidList : batchList) {
                    JSONArray openidJsonArray = new JSONArray();
                    childOpenidList.forEach(model->{
                        JSONObject openidJson = new JSONObject();
                        openidJson.put("openid", model);
                        openidJson.put("lang", "zh_CN");
                        openidJsonArray.add(openidJson);
                    });
                    JSONObject jsonParam = new JSONObject();
                    jsonParam.put("user_list", openidJsonArray);
                    String unionUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="+WechatMsgUtils.getToken();;
                    logger.info("调用获取用户信息,请求url:{}, 请求body:{}", unionUrl, jsonParam.toJSONString());
                    String getUnionResult = HttpUtil.post(unionUrl, jsonParam.toJSONString());
                    logger.info("获取公众号union列表:{}", getUnionResult);
                    JSONObject unionJson = JSONObject.parseObject(getUnionResult);
                    JSONArray unionJsonArray = unionJson.getJSONArray("user_info_list");
                    for (int index = 0 ; index<unionJsonArray.size(); index ++){
                        JSONObject json = unionJsonArray.getJSONObject(index);
                        if(StringUtils.isNotEmpty(json.getString("unionid") )&& StringUtils.isNotEmpty(unionId)){
                            if(json.getString("unionid").equals(unionId)){
                                Worker updateWorker = new Worker();
                                updateWorker.setWorkerId(worker.getWorkerId());
                                updateWorker.setWxOpenId(json.getString("openid"));
                                logger.info("关联后的worker信息:{}", worker);
                                workerService.updateWorker(updateWorker);
                                flag = true;
                                break;
                            }
                        }
                    }
                    if(flag){
                        break;
                    }
                }
            }
        }
        return AjaxResult.success(true);
    }


    @GetMapping("/neCheck")
    @ResponseBody
    public AjaxResult neCheck(HttpServletRequest request) {
        try {
            String url;
            boolean flag = false;
            String deptId = request.getHeader("deptId");
            String from = request.getHeader("from");
            SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
            String code = request.getHeader("code");
            if("customer".equals(from)){
                url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getWxAppId() + "&secret=" + sysDeptConfig.getWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
            }else {
                url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getServWxAppId() + "&secret=" + sysDeptConfig.getServWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
            }
            String data = HttpUtils.sendGet(url, null);
            JSONObject result = JSONObject.parseObject(data);
            // 如果是师傅端,需要调用公众号的获取用户列表接口 -- 遍历列表去找到unionId和openid关联并入库
            if(!"customer".equals(from)){
                String openid = result.getString("openid");
                String unionId = result.getString("unionid");
                // 查询openid是否入库，已经入库则不管
                Worker param = new Worker();
                param.setOpenId(openid);
                Worker worker = workerService.selectByOpenId(param);
                if(worker != null){
                    // 公众号token
                    String wxToken = WechatMsgUtils.getToken();
                    String wxUserOpenidList = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+wxToken+"&next_openid=");
                    logger.info("公众号获取的用户列表集合:{}", wxUserOpenidList);
                    JSONObject wxOpenidJson = JSONObject.parseObject(wxUserOpenidList);
                    JSONObject openIdListJson = wxOpenidJson.getJSONObject("data");
                    List<String> openidList = openIdListJson.getObject("openid", ArrayList.class);
                    List<List<String>> batchList = ListUtil.partition(openidList, 99);
                    for (List<String> childOpenidList : batchList) {
                        JSONArray openidJsonArray = new JSONArray();
                        childOpenidList.forEach(model->{
                            JSONObject openidJson = new JSONObject();
                            openidJson.put("openid", model);
                            openidJson.put("lang", "zh_CN");
                            openidJsonArray.add(openidJson);
                        });
                        JSONObject jsonParam = new JSONObject();
                        jsonParam.put("user_list", openidJsonArray);
                        String unionUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="+WechatMsgUtils.getToken();;
                        logger.info("调用获取用户信息,请求url:{}, 请求body:{}", unionUrl, jsonParam.toJSONString());
                        String getUnionResult = HttpUtil.post(unionUrl, jsonParam.toJSONString());
                        logger.info("获取公众号union列表:{}", getUnionResult);
                        JSONObject unionJson = JSONObject.parseObject(getUnionResult);
                        JSONArray unionJsonArray = unionJson.getJSONArray("user_info_list");
                        for (int index = 0 ; index<unionJsonArray.size(); index ++){
                            JSONObject json = unionJsonArray.getJSONObject(index);
                            if(StringUtils.isNotEmpty(json.getString("unionid") )&& StringUtils.isNotEmpty(unionId)){
                                if(json.getString("unionid").equals(unionId)){
                                    Worker updateWorker = new Worker();
                                    updateWorker.setWorkerId(worker.getWorkerId());
                                    updateWorker.setWxOpenId(json.getString("openid"));
                                    logger.info("关联后的worker信息:{}", worker);
                                    workerService.updateWorker(updateWorker);
                                    flag = true;
                                    break;
                                }
                            }
                        }
                        if(flag){
                            break;
                        }
                    }
                }
            }
            return AjaxResult.success(flag);
        }catch (Exception e){
            return AjaxResult.success(false);
        }
    }


    @GetMapping("/openid")
    @ResponseBody
    public String openId(HttpServletRequest request) throws Exception {
        String code = request.getParameter("code");
        JSONObject wxUser = WxUtils.getOpenid(code, "wx404f2439a8c24e15", "49ade04a817067fe2d65ab2f17afce75");
        return wxUser.getString("openid");
    }

    @PostMapping("/unlimited/wxacode")
    @ResponseBody
    public AjaxResult getUnlimitedWxacode(@RequestBody JSONObject requestObj) throws Exception {
        String base64Code = null;

        try {
            String scene = requestObj.getString("scene");
            String envVersion = requestObj.getString("env_version");
            Integer width = requestObj.getInteger("width");
            String from = requestObj.getString("from");
            String deptId = requestObj.getString("deptId");

            SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
            String token = null;
            if("customer".equals(from)) {
                token = getAccessToken(sysDeptConfig.getWxAppId(), sysDeptConfig.getWxSecret());
            } else {
                token = getAccessToken(sysDeptConfig.getServWxAppId(), sysDeptConfig.getServWxSecret());
            }
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + token;
            JSONObject params = new JSONObject();
//        params.put("access_token", token);
            params.put("scene", scene);
            params.put("env_version", envVersion);
            params.put("width", width);

            byte[] byteRes = HttpUtils.sendPostForBuffer(url, params.toJSONString());
            base64Code = new String(Base64.encodeBase64(byteRes));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(ExceptionUtils.getStackTrace(e));
            return AjaxResult.error(e.getMessage());
        }

        return AjaxResult.success("", base64Code);
    }

    private static String getAccessToken(String appId, String appSecret){
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId +"&secret=" + appSecret;
        String result = HttpUtils.sendGet(url);
        return JSONObject.parseObject(result).getString("access_token");
    }

    private String getPhoneNumber(String code, String accessToken){
        JSONObject params = new JSONObject();
        params.put("code", code);
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
        String result = HttpUtils.sendPost(url, params.toString());
        logger.info("获取手机号，请求结果=" + result);
        String errCode = JSONObject.parseObject(result).getString("errcode");
        if("0".equals(errCode)){
            return JSONObject.parseObject(result).getJSONObject("phone_info").getString("purePhoneNumber");
        }else {
            throw new ServiceException("获取手机号码异常");
        }
    }

    /**
     * 验证微信签名
     */
    public static boolean checkSignature(String signature, String timestamp,
                                         String nonce, String token) {
        // 1.将token、timestamp、nonce三个参数进行字典序排序
        String[] arr = new String[]{token, timestamp, nonce};
        Arrays.sort(arr);
        // 2. 将三个参数字符串拼接成一个字符串进行sha1加密
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        content = null;
        // 3.将sha1加密后的字符串可与signature对比，标识该请求来源于微信
        return tmpStr != null && tmpStr.equals(signature.toUpperCase());
    }

    private static String byteToStr(byte[] byteArray) {
        StringBuilder strDigest = new StringBuilder();
        for (int i = 0; i < byteArray.length; i++) {
            strDigest.append(byteToHexStr(byteArray[i]));
        }
        return strDigest.toString();
    }

    private static String byteToHexStr(byte mByte) {
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }


}
