package com.yeejoin.precontrol.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.util.StringUtil;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.precontrol.common.entity.AppMenuConfig;
import com.yeejoin.precontrol.common.entity.Person;
import com.yeejoin.precontrol.common.entity.WechatRelation;
import com.yeejoin.precontrol.common.param.MobileLoginParam;
import com.yeejoin.precontrol.common.service.IPersonService;
import com.yeejoin.precontrol.common.service.ISafetyService;
import com.yeejoin.precontrol.common.service.IWechatRelationService;
import com.yeejoin.precontrol.common.utils.CommonResponseUtil;
import com.yeejoin.precontrol.common.utils.HttpUtils;
import com.yeejoin.precontrol.common.utils.RedisUtil;
import com.yeejoin.precontrol.common.utils.XmlUtil;
import com.yeejoin.precontrol.common.utils.aes.WXBizMsgCrypt;
import com.yeejoin.precontrol.common.vo.PersonVo;
import com.yeejoin.precontrol.common.vo.ResponeVo;
import com.yeejoin.precontrol.common.vo.UserRegistrationVo;
import com.yeejoin.precontrol.controller.publics.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.typroject.tyboot.core.foundation.context.RequestContext;

import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value = "/safe")
@Api(tags = "安全api")
public class SafetyController extends BaseController {
    private final Logger log = LoggerFactory.getLogger(SafetyController.class);

    /**
     * 人员服务
     */
    @Autowired
    private IPersonService personService;

    @Autowired
    private ISafetyService iSafetyService;

    @Value("${amos.agency.code}")
    String agencyCode;
    @Value("${smallProgram.public.encodingAesKey}")
    String encodingAesKey;
    /**
     * 公众号appid
     */
    @Value("${smallProgram.public.appid}")
    private String publicAppId;
    /**
     * 公众号secret
     */
    @Value("${smallProgram.public.secret}")
    private String publicSecret;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private IWechatRelationService wechatRelationService;

    /**
     * 用户选择公司信息
     */
    @ApiOperation(value = "登陆用户信息", notes = "登陆用户信息")
    @GetMapping(value = "/curPerson")
    public Object curPerson() {
        AgencyUserModel userInfo = this.getUserInfo();
        Long userNumber = userInfo.getSequenceNbr();
        PersonVo personVo = personService.getPersonVoByAccountNumber(String.valueOf(userNumber));
        if (personVo == null) {
            return CommonResponseUtil.failure("账号未绑定！！");
        }
        return personVo;
    }

//    /**
//     * 移动端登录 - 之前代码，年底驻场修改
//     */
//    @ApiOperation(value = "移动端登录", notes = "移动端登录")
//    @PostMapping(value = "/mobile/login")
//    public Object mobileLogin(@ApiParam(value = "账号", required = true) @RequestBody MobileLoginUserParam param) {
//
//        try {
//            JSONObject jsonObject = null;
//            IdPasswordAuthModel dPasswordAuthModel = new IdPasswordAuthModel();
//            dPasswordAuthModel.setLoginId(param.getUserName());
//            dPasswordAuthModel.setPassword(param.getPassword());
//            HttpHeaders headers = new HttpHeaders();
//            headers.setContentType(MediaType.APPLICATION_JSON);
//            headers.set("Content-Type", "application/json");
//            headers.set("product", product);
//            HttpEntity httpEntity = new HttpEntity<>(dPasswordAuthModel, headers);
//            FeignClientResult feignClientResult = restTemplate.postForObject(
//                    "http://" + securityName + "/privilege/v1/auth/idpassword", httpEntity, FeignClientResult.class);
//            if (feignClientResult.getStatus() == 200) {
//                Map map = (Map) feignClientResult.getResult();
//                map.put("appKey", appKey);
//                map.put("product", product);
//                String jsonStr = JSON.toJSONString(map);
//                jsonObject = JSONObject.parseObject(jsonStr);
//            } else {
//                return CommonResponseUtil.failure(feignClientResult.getMessage());
//            }
//            if (jsonObject != null) {
//                JSONObject result = new JSONObject();
//                result.put("token", jsonObject.getString("token"));
//                result.put("personId", jsonObject.getString("userId"));
//                result.put("appKey", jsonObject.getString("appKey"));
//                result.put("product", jsonObject.getString("product"));
//                return result;
//            }
//            return CommonResponseUtil.failure("登录失败");
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.error("移动端登录异常", e);
//            return CommonResponseUtil.failure("系统繁忙，请稍后再试");
//        }
//    }

    @ApiOperation(value = "移动端登录", notes = "移动端登录")
    @PostMapping(value = "/mobile/login")
    public Object loginFromApp(@RequestBody MobileLoginParam param) {
        buildRequestContext();
        return iSafetyService.loginFromApp(param);
    }


    @ApiOperation(value = "移动端注册提交")
    @PostMapping(value = "/mobile/register")
    public Object registerFromApp(@RequestBody UserRegistrationVo vo) {
        setPlatFormAccess();
        return iSafetyService.registerFromApp(vo);
    }

    @ApiOperation(value = "移动端注册历史")
    @PostMapping(value = "/mobile/register/history")
    public Object registerHistory(@RequestBody String phoneNo) {
        setPlatFormAccess();
        return iSafetyService.getRegisterHistory(phoneNo);
    }

    /**
     * 获取平台所有用户
     *
     * @return
     */
    @RequestMapping(value = "/amosUser", method = RequestMethod.GET)
    @ApiOperation(httpMethod = "GET", value = "获取平台所有用户", notes = "获取平台所有用户")
    public Object nationSelect() {
        AgencyUserModel userInfo = this.getUserInfo();
        List<CompanyModel> companys = userInfo.getCompanys();
        if (companys != null && !companys.isEmpty()) {
            //获取平台机构
            CompanyModel companyModel = companys.get(0);

            if (this.getToken() != null) {
                RequestContext.setToken(getToken());
                RequestContext.setProduct(getProduct());
                RequestContext.setAppKey(getAppKey());
                try {
                    FeignClientResult<List<AgencyUserModel>> amosUserList =
                            Privilege.agencyUserClient.queryByCompanyId(companyModel.getSequenceNbr(), null, null, false);
                    return amosUserList.getResult();
                } catch (Exception e) {
                    e.printStackTrace();
                    return CommonResponseUtil.failure(e.getMessage());
                }
            }
        }
        return CommonResponseUtil.failure();

    }


    /**
     * 获取未绑定用户
     */
    @RequestMapping(value = "/unboundUser", method = RequestMethod.GET)
    @ApiOperation(httpMethod = "GET", value = " 获取未绑定用户", notes = " 获取未绑定用户")
    public Object unboundUser() {
        AgencyUserModel userInfo = this.getUserInfo();
        List<CompanyModel> companys = userInfo.getCompanys();
        if (companys != null && !companys.isEmpty()) {
            //获取平台机构
            CompanyModel companyModel = companys.get(0);

            if (this.getToken() != null) {
                RequestContext.setToken(getToken());
                RequestContext.setProduct(getProduct());
                RequestContext.setAppKey(getAppKey());
                try {
                    FeignClientResult<List<AgencyUserModel>> res =
                            Privilege.agencyUserClient.queryByCompanyId(companyModel.getSequenceNbr(), null, null, false);
                    if (200 == res.getStatus()) {
                        List<AgencyUserModel> result = res.getResult();
                        List<String> bindUserSeqs = personService.selectBindUserSeqs();

                        List<AgencyUserModel> unboundUser = result.stream().filter(u -> !bindUserSeqs.contains(String.valueOf(u.getSequenceNbr()))).collect(Collectors.toList());
                        return unboundUser;
                    } else {
                        return CommonResponseUtil.failure(res.getDevMessage());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return CommonResponseUtil.failure(e.getMessage());
                }
            }
        }
        return CommonResponseUtil.failure();

    }

    /*@ApiOperation("获取验证码")
    @GetMapping("/getAuthCode")
    public void getAuthCode(@RequestParam String phoneNo){
        iSafetyService.getAuthCode(phoneNo);
    }*/

    @ApiOperation("获取验证码")
    @GetMapping("/getAuthCode")
    public void getAuthCode(@RequestParam String phoneNo) {
        iSafetyService.getAuthCode(phoneNo);
    }

    @ApiOperation(value = "小程序菜单查询", notes = "已经配置的菜单")
    @GetMapping("/permission/list")
    public List getAppMenuList() {
        String userId = getUserId();
        return iSafetyService.permissionMenuList(userId);
    }

    @ApiOperation(value = "小程序全部菜单查询", notes = "可选择的菜单")
    @GetMapping("/all/permission")
    public List getAllMenu() {
        String userId = getUserId();
        return iSafetyService.allPermissionMenuList(userId);
    }

    @ApiOperation(value = "小程序菜单配置保存", notes = "小程序菜单配置保存")
    @PostMapping("/permission")
    public Boolean savePermission(@RequestBody List<AppMenuConfig> list) {
        String userId = getUserId();
        return iSafetyService.savePermission(userId, list);
    }

    /**
     * 微信验证token
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @ApiOperation(value = "微信验证token", notes = "微信验证token")
    @GetMapping(value = "/checkToken")
    public String checkToken(@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp,
                             @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr) {
        //排序
        String[] arr = {agencyCode, timestamp, nonce};
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        //sha1Hex 加密
        MessageDigest md = null;
        String temp = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(content.toString().getBytes());
            temp = byteToStr(digest);
            log.info("加密后的token:" + temp);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        if ((temp.toLowerCase()).equals(signature)) {
            return echostr;
        }
        return null;
    }

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

    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;
    }


    /**
     * 用户关注公众号或在公众号点击请求此接口
     */
    @ApiOperation(value = "用户关注公众号或在公众号点击请求此接口", notes = "用户关注公众号或在公众号点击请求此接口")
    @PostMapping(value = "/checkToken")
    public Object wxPublicSend(HttpServletRequest request) {
        try {
            // 签名
            String msgSignature = request.getParameter("msg_signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 第一次解析
            JSONObject jsonObject = XmlUtil.xmlToMap(request);
            if (jsonObject != null) {
                String encrypt = jsonObject.getString("Encrypt");
                WXBizMsgCrypt pc = new WXBizMsgCrypt(agencyCode, encodingAesKey, publicAppId);
                String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
                String fromXML = String.format(format, encrypt);
                String result2 = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML);
                System.out.println("解密后明文: " + result2);
                // 第二次解析
                /**
                 * ToUserName : gh_adf6cc0ea7c6
                 * FromUserName : omzjg09wxUbgL-aNFaixj4YYr45M
                 * CreateTime : 1627383303
                 * MsgType : text
                 * Content : 滴滴
                 * MsgId : 23298528794961090
                 * */
                JSONObject jsonInfo = XmlUtil.xmlToMap(result2);
                if (jsonInfo != null) {
                    // 公众号的openId
                    String openId = jsonInfo.getString("FromUserName");
                    String accessToken = getAccessToken();
                    String unionId = getPublicUnionIdByOpenId(accessToken, openId);
                    // 判断数据是否存在
                    WechatRelation wechatRelation = wechatRelationService.getOne(new LambdaQueryWrapper<WechatRelation>().eq(WechatRelation::getUnionId, unionId));
                    if (wechatRelation == null) {
                        wechatRelation = new WechatRelation();
                        wechatRelation.setPublicOpenId(openId);
                        wechatRelation.setUnionId(unionId);
                        wechatRelation.setCreateDate(new Date());
                        wechatRelationService.save(wechatRelation);
                    } else {
                        // 判断 公众号openId 是否存在
                        if (StringUtil.isEmpty(wechatRelation.getPublicOpenId())) {
                            wechatRelation.setPublicOpenId(openId);
                            wechatRelationService.updateById(wechatRelation);
                            if(wechatRelation.getPersonId() != null){
                                Person person = personService.getById(wechatRelation.getPersonId());
                                if (person != null && StringUtil.isEmpty(person.getOpenId())) {
                                    Person newPerson = new Person();
                                    newPerson.setId(person.getId());
                                    newPerson.setOpenId(openId);
                                    personService.updateById(newPerson);
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return "ok";
        }
        return "ok";
    }

    /*
     * 获取公众号 accesstoken
     * (non-Javadoc)
     * @see com.yspro.service.PubUserService#getAccessToken()
     */
    public String getAccessToken() throws Exception {
        String accessToken = (String) redisUtil.get("accessToken");
        if (StringUtil.isNotEmpty(accessToken)) {
            return accessToken;
        } else {
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + publicAppId + "&secret=" + publicSecret;
            ResponeVo responeVo = HttpUtils.post(url, "");
            JSONObject jsonResult = JSONObject.parseObject(responeVo.getContent());
            // 成功后 返回参数中没有 errcode
            if (jsonResult != null) {
                accessToken = jsonResult.getString("access_token");
                if (StringUtil.isNotEmpty(accessToken)) {
                    // 有效时长 7200s == 2h
                    String expires_in = jsonResult.getString("expires_in");
                    redisUtil.set("accessToken", accessToken, Long.valueOf(expires_in));
                    log.info("accessToken的值为：{} ", accessToken);
                } else {
                    log.info("获取公众号 accessToken 失败， {}", jsonResult.toJSONString());
                }
            } else {
                log.info("获取公众号 accessToken 失败， {}", jsonResult.toJSONString());
            }
        }
        return accessToken;
    }

    /**
     * 通过公众号openId 获取 unionId
     *
     * @param accessToken
     * @return
     */
    public String getPublicUnionIdByOpenId(String accessToken, String openId) {
        String unionId = "";
        if (StringUtil.isEmpty(accessToken) || StringUtil.isEmpty(openId)) {
            return null;
        }
        try {
            List<JSONObject> user_list = new ArrayList<>();
            JSONObject map = new JSONObject();
            map.put("openid", openId);
            map.put("lang", "zh_CN");
            user_list.add(map);
            JSONObject json = new JSONObject();
            //根据公众号openid获取公众号unionid
            String requestUrl2 = new StringBuffer().append("https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=").append(accessToken).toString();
            //json转换成map
            json.put("user_list", user_list);
            ResponeVo responeVoStr = HttpUtils.post(requestUrl2, json.toJSONString());
            JSONObject strArr = JSONObject.parseObject(responeVoStr.getContent());
            List<JSONObject> userInfoList = (List<JSONObject>) strArr.get("user_info_list");
            if (userInfoList.size() > 0) {
                for (JSONObject objectMap : userInfoList) {
                    System.out.println("****:" + objectMap.toJSONString());
                    unionId = objectMap.getString("unionid");
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            return null;
        }
        return unionId;
    }

//    public static void main(String[] args) {
//        String agencyCode = "JEPCC",
//                encodingAesKey = "5lPa0OQzUtEqXXW1mzQTKkPomaPqxgCkrE9WRnuGEF2",
//                publicAppId = "wxf6f295ce82aa4aab",
//                encrypt = "kmWDvqKLVOM1yS04cx0KG36Swn0Md6CwnRINPgK2FNCIdd0Ks0yMOSYhhhibn8QmcV7bx8PXmxexTs3ukAyq3Z3VFkP8w+O/hARf8Rgx6+x8R6xytN0g2Zry9dMdmoG8+CqZ/qKIYiIysxfr8zPDxljO7+DhOPJbkSqJ547v8vDgtiHCyQ1hjldcCL9IrodELFq/DKKA69dzNTNMgPt65iFm/oVDHfiMOGjOQVfPCRSypJxcR5TlTa+SaFU+LARbytdL7sk/s0kZs0kNR1cpG1LEiQPVQeMdbu8Ie1hLhng99Ze82sRmOzM6QGdDpRNL66Iqgx+l7TtiNlL2OSzqlJLTgtDqWeAih7tPld6ab9MBTzQHxRVK+PwcdsyKHL3CjYLdDmK99oNjzqHUsLA+Oyv60UhaBprIMexKUFTZric=";
//        try {
//            String msgSignature = "03e9c3e7a141130f751fa674249f300a1299a4f3";
//            // 时间戳
//            String timestamp ="1627383304";
//            // 随机数
//            String nonce = "171714103";
//            String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
//            String fromXML = String.format(format, encrypt);
//            WXBizMsgCrypt pc = new WXBizMsgCrypt(agencyCode, encodingAesKey, publicAppId);
//            String result2 = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML);
//            System.out.println("解密后明文: " + result2);
//            Document doc = null;
//            try {
//                doc = DocumentHelper.parseText(result2);
//            } catch (DocumentException e) {
//                e.printStackTrace();
//            }
//            Element root = doc.getRootElement();
//            Iterator it = root.elementIterator();
//            while (it.hasNext()) {
//                Element element = (Element) it.next();
//                System.out.println(element.getName() + " : " + element.getTextTrim());
//            }
//
//        } catch (Exception e) {
//            e.getStackTrace();
//            System.out.println("error");
//        }
//    }
}
