package com.tuoheng.miniprogram.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tuoheng.common.core.config.common.CommonConfig;
import com.tuoheng.common.core.utils.DateUtils;
import com.tuoheng.common.core.utils.JsonResult;
import com.tuoheng.common.core.utils.StringUtils;
import com.tuoheng.miniprogram.dao.UserAuthorizeMapper;
import com.tuoheng.miniprogram.dao.UserMapper;
import com.tuoheng.miniprogram.entity.User;
import com.tuoheng.miniprogram.entity.UserAuthorize;
import com.tuoheng.miniprogram.entity.dto.TemplateMinDto;
import com.tuoheng.miniprogram.entity.wx.WxMessageRequest;
import com.tuoheng.miniprogram.enums.*;
import com.tuoheng.miniprogram.param.WxSendMessageParam;
import com.tuoheng.miniprogram.service.IWxService;
import com.tuoheng.miniprogram.utils.CurrentUserUtil;
import com.tuoheng.miniprogram.utils.GetOpenIdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author ChengWang
 * @Date 2023/6/23
 */
@Service
@Slf4j
public class WxServiceImpl implements IWxService {

    @Autowired
    private UserAuthorizeMapper userAuthorizeMapper;

    @Autowired
    private UserMapper userMapper;

    private static  String accessToken;

    private static long expiresTime;


    /**
     * 根据code获取openId
     * @param code
     * @return
     */
    @Override
    public JsonResult openid(String code) {
        String userId = CurrentUserUtil.getUserId();
        String openidResult = GetOpenIdUtil.getopenid(code, CommonConfig.appId, CommonConfig.appSecret);
        if(null != JSONObject.parseObject(openidResult).getInteger("errcode") ||
                StringUtils.isNotEmpty(JSONObject.parseObject(openidResult).getString("errmsg"))){
            return JsonResult.error(JSONObject.parseObject(openidResult).getInteger("errcode").intValue(),
                    JSONObject.parseObject(openidResult).getString("errmsg"));
        }
        String openid = JSONObject.parseObject(openidResult).getString("openid");
        if(StringUtils.isEmpty(openid)){
            log.error("获取openid失败：",openidResult);
            return JsonResult.error("获取openid失败");
        }
        //根据当前登录用户id查询授权表是否存在一条授权数据
        UserAuthorize beforeUserAuthorize = userAuthorizeMapper.selectOne(Wrappers.<UserAuthorize>lambdaQuery()
                .eq(UserAuthorize::getUserId, userId)
                .eq(UserAuthorize::getMark, MarkEnum.VALID.getCode()));
        if(ObjectUtil.isNull(beforeUserAuthorize)){
            UserAuthorize userAuthorize = new UserAuthorize();
            if(StringUtils.isNotEmpty(openid)){
                //查询出来openId数据入库
                userAuthorize.setOpenId(openid);
            }
            userAuthorize.setUserId(userId);
            userAuthorize.setCreateTime(DateUtils.now());
            if(StringUtils.isNotEmpty(userId)){
                userAuthorize.setCreateUser(userId);
            }
            int result = userAuthorizeMapper.insert(userAuthorize);

            if(result<=0){
                return JsonResult.error("授权数据入库失败");
            }
        }
        //关联登录用户,已经做过授权 修改授权标识
        User user = CurrentUserUtil.getUserInfo();
        if(ObjectUtil.isEmpty(user)){
            return JsonResult.error(UserCodeEnum.USER_IS_NULL.getCode(),UserCodeEnum.USER_IS_NULL.getMsg());
        }
        user.setAuthorize(AuthorizeStatusEnum.AUTHORIZE_ON.getCode());
        user.setUpdateTime(DateUtils.now());
        user.setUpdateUser(userId);
        int count = userMapper.updateById(user);
        if(count <= 0){
            return JsonResult.error("用户授权标识更新失败");
        }
        return JsonResult.success();
    }

    /**
     * 获取access_code值
     * @return
     */
    public String getAccessToken(){
        //判断accessToken是否已经过期，如果国企需要重新获取
        if(accessToken == null || expiresTime <System.currentTimeMillis()){
            RestTemplate restTemplate = new RestTemplate();
            Map<String,String> params = new HashMap<>(2);
            params.put("APPID",CommonConfig.appId);
            params.put("APPSECRET",CommonConfig.appSecret);
            ResponseEntity<String> responseEntity = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}", String.class, params);
            String body = responseEntity.getBody();
            JSONObject object = JSON.parseObject(body);
            Integer errcode = object.getInteger("errcode");
            if(errcode != null && errcode != 0){
                String errmsg = object.getString("errmsg");
                log.info("请求accessToken失败,返回码:" + errcode + "错误信息:" + errmsg);
                throw new RuntimeException("请求获取accessToken失败");
            }
            //缓存accessToken
            accessToken = object.getString("access_token");
            log.info("获取的accessToken的值:" + accessToken);
            //设置accessToken的失效时间
            Long expires_in = object.getLong("expires_in");
            //失效时间 = 当前时间+有效期(提前一分钟，也可以不提前)
            expiresTime = System.currentTimeMillis() + (expires_in - 60) * 1000;
        }

        return accessToken;
    }

    /**
     * 发送消息
     * @param wxMessageRequest
     * @return
     */
    @Override
    public JsonResult sendMessage(WxMessageRequest wxMessageRequest) {
        JsonResult result = this.check(wxMessageRequest);
        if(result.getCode() != 0){
            //正常返回,信息提示
            return JsonResult.success(result.getCode(),result.getMsg());
        }
        List<User> userList = (List<User>) result.getData();
        boolean isSend =false;
        //对用户进行遍历推送消息
        for (User user : userList) {
            String userId = user.getId();
            if(user.getAuthorize() == AuthorizeStatusEnum.AUTHORIZE_DOWN.getCode()){
                //本次结束,进入下次循环
                continue;
            }
            if(user.getAuthorize() == AuthorizeStatusEnum.AUTHORIZE_ON.getCode()
                    && user.getSubscribeTimes() == SubscribeTimesEnum.SUBSCRIBE_TIMES_NO_ONE.getCode()){
                continue;
            }
            //获取当前登录openId
            UserAuthorize userAuthorize = userAuthorizeMapper.selectOne(Wrappers.<UserAuthorize>lambdaQuery()
                    .eq(UserAuthorize::getUserId, userId)
                    .eq(UserAuthorize::getMark, MarkEnum.VALID.getCode()));
            //授权数据校验
            JsonResult jsonResult = this.getUserAuthorize(userAuthorize);
            if(jsonResult.getCode() != 0){
                continue;
            }
            String openId = userAuthorize.getOpenId();
            RestTemplate restTemplate = new RestTemplate();
            //发送消息订阅
            String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + getAccessToken();
            WxSendMessageParam param = new WxSendMessageParam();
            param.setPage("/package_question/pages/taskList/taskList");
            param.setTouser(openId);
            param.setTemplate_id(CommonConfig.templateId);
            Map<String, TemplateMinDto> data = new HashMap<>(3);
            //消息模板{{time12.DATA}} {{thing4.DATA}} {{thing13.DATA}}  时间格式一定是这样的2022-01-13 02:31:36
            ResponseEntity<String> responseEntity = null;
            try {
                data.put("time12",new TemplateMinDto(wxMessageRequest.getCreateTime()));
                data.put("thing4",new TemplateMinDto(wxMessageRequest.getQuestionName()));
                data.put("thing13",new TemplateMinDto(wxMessageRequest.getQuestionDesc()));
                param.setData(data);

                responseEntity = restTemplate.postForEntity(url, param, String.class);
                String messageBody = responseEntity.getBody();
                Integer errcode = JSONObject.parseObject(messageBody).getInteger("errcode").intValue();
                if(errcode != null && errcode == 0){
                    //修改用户订阅次数
                    user.setSubscribeTimes(SubscribeTimesEnum.SUBSCRIBE_TIMES_NO_ONE.getCode());
                    int count = userMapper.updateById(user);
                    if(count <= 0){
                        throw new RuntimeException("更新用户订阅次数失败");
                    }
                }else if(errcode != null && errcode != 0){
                    String errmsg = JSONObject.parseObject(messageBody).getString("errmsg");
                    log.info("请求accessToken失败,返回码:" + errcode.intValue() + "错误信息:" + errmsg);
                    //return JsonResult.error(errcode.intValue(),errmsg);
                }
                JSONObject jsonObject = JSON.parseObject(messageBody);
                if(Objects.nonNull(jsonObject)){
                    log.info("openId:" + openId + "发送消息返回内容:" + jsonObject.toJSONString());
                }
                isSend = true;
            } catch (RestClientException e) {
                log.info("openId:"+ openId +"发送消息异常报错:"+e);
                e.printStackTrace();
            }

        }

        return JsonResult.success(isSend);

    }

    /**
     * 校验权限数据
     * @param userAuthorize
     * @return
     */
    private JsonResult getUserAuthorize(UserAuthorize userAuthorize) {
        if(ObjectUtil.isNull(userAuthorize)){
            return JsonResult.error(UserAuthorizeEnum.UNAUTHORIZED.getCode(),UserAuthorizeEnum.UNAUTHORIZED.getMsg());
        }
        if(StringUtils.isEmpty(userAuthorize.getOpenId())){
            return JsonResult.error(UserAuthorizeEnum.OPEN_ID_IS_NULL.getCode(),UserAuthorizeEnum.OPEN_ID_IS_NULL.getMsg());
        }
        return JsonResult.success();
    }

    private JsonResult check(WxMessageRequest wxMessageRequest) {
        //传参校验
        if(StringUtils.isEmpty(wxMessageRequest.getTenantId())){
            return JsonResult.error(WeiXinRequestEnum.TENANT_ID_NOT_EXIST.getCode(),WeiXinRequestEnum.TENANT_ID_NOT_EXIST.getMsg());
        }
        if(StringUtils.isEmpty(wxMessageRequest.getInspectionId())){
            return JsonResult.error(WeiXinRequestEnum.INSPECTION_ID_IS_NULL.getCode(),WeiXinRequestEnum.INSPECTION_ID_IS_NULL.getMsg());
        }
        if(StringUtils.isEmpty(wxMessageRequest.getDeptId())){
            return JsonResult.error(WeiXinRequestEnum.DEPT_ID_IS_NULL.getCode(),WeiXinRequestEnum.DEPT_ID_IS_NULL.getMsg());
        }
        if(StringUtils.isEmpty(wxMessageRequest.getCreateTime())){
            return JsonResult.error(WeiXinRequestEnum.CREATE_TIME_IS_NULL.getCode(),WeiXinRequestEnum.CREATE_TIME_IS_NULL.getMsg());
        }
        if(StringUtils.isEmpty(wxMessageRequest.getQuestionName())){
            return JsonResult.error(WeiXinRequestEnum.INSPECTION_NAME_NOT_EXIST.getCode(),WeiXinRequestEnum.INSPECTION_NAME_NOT_EXIST.getMsg());
        }
        if(StringUtils.isEmpty(wxMessageRequest.getQuestionDesc())){
            return JsonResult.error(WeiXinRequestEnum.QUESTION_DESC_NOT_EXIST.getCode(),WeiXinRequestEnum.QUESTION_DESC_NOT_EXIST.getMsg());
        }
        //根据租户id查询用户列表
        List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery()
                .eq(User::getMark, MarkEnum.VALID.getCode())
                .eq(User::getDeptId, wxMessageRequest.getDeptId())
                .eq(User::getStatus, 1));
        if(CollectionUtil.isEmpty(users) || users.size() == 0){
            return JsonResult.error("此租户下没有用户");
        }
        return JsonResult.success(users);
    }
}
