package com.storlead.wecom.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.ImmutableMap;
import com.storlead.framework.common.vo.user.UserVO;
import com.storlead.wecom.pojo.vo.CorpWeChatUserVO;
import com.storlead.wecom.pojo.vo.WechatAppBO;
import com.storlead.wecom.pojo.vo.WechatToken;
import com.storlead.wecom.properties.CorpWeChatConstants;
import com.storlead.wecom.properties.CorpWeChatProperties;
import com.storlead.wecom.service.CorpWeChatService;
import com.storlead.wecom.service.WechatTokenService;
import com.storlead.wecom.util.CorpWechatUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 企业微信实现类
 * CorpWeChatServiceImpl
 *
 * @author blank
 * @date 2021-6-15 下午 12:10
 */
@Slf4j
@Service
public class CorpWeChatServiceImpl implements CorpWeChatService {

    @Resource
    private WechatTokenService wechatTokenService;

    @Value("${environment}")
    private  String environment;

    @Autowired
    private RedissonClient redisson;


    /**
     * 获取企业微信ACCESS_TOKEN
     *
     * @return cn.hutool.json.JSONObject
     * @author blank
     * @date 2021-3-8 下午 12:10
     */
    @Override
    public WechatToken getAccessToken() {
        //先从DB中读取 如果过期再重新获取
        WechatToken accessToken = wechatTokenService.getOne(new LambdaQueryWrapper<WechatToken>().eq(WechatToken::getType, CorpWeChatConstants.TOKEN_TYPE_ACCESS_TOKEN));
        if (accessToken != null && accessToken.getExpiresIn().isAfter(LocalDateTime.now())) {
            return accessToken;
        }
        String lockKey = "create-wechat-token-update";
        RLock redissonLock = redisson.getLock(lockKey);
        redissonLock.lock();
        WechatToken wechatToken = null;
        try {
            wechatToken = CorpWechatUtil.getAccessToken(CorpWeChatConstants.GET_ACCESS_TOKEN_URL, CorpWeChatProperties.getCorpId(), CorpWeChatProperties.getCorpAgentSecret());
            wechatTokenService.removeByMap(ImmutableMap.of("type", CorpWeChatConstants.TOKEN_TYPE_ACCESS_TOKEN));
            wechatTokenService.save(wechatToken);
        } finally {
            redissonLock.unlock();
        }
        return wechatToken;
    }

    /**
     * 向TX企业微信API 接口获取 通讯录 AccessToken
     *
     * @return com.storlead.web.model.vo.WeChatAccessTokenVO
     * @author blank
     * @date 2021-3-8 下午 2:59
     */
    private WechatToken getAddressAccessTokenFromTencent() {
        return CorpWechatUtil.getAccessToken(CorpWeChatConstants.GET_ACCESS_TOKEN_URL, CorpWeChatProperties.getCorpId(), CorpWeChatProperties.getCorpAddressSecret());
    }

    /**
     * 获取企业微信 JS ticket
     *
     * @return com.storlead.web.model.vo.WeChatAccessTokenVO
     * @author blank
     * @date 2021-3-8 下午 2:30
     */
    @Override
    public WechatToken getJSApiTicket() {

        WechatToken accessToken = wechatTokenService.getOne(new LambdaQueryWrapper<WechatToken>().eq(WechatToken::getType, CorpWeChatConstants.TOKEN_TYPE_TICKET));
        if (accessToken != null && accessToken.getExpiresIn().isAfter(LocalDateTime.now())) {
            return accessToken;
        }

        String token = getAccessToken().getToken();
        WechatToken wechatToken = CorpWechatUtil.getJSApiTicket(CorpWeChatConstants.GET_JSAPI_TICKET_URL, token);
        wechatTokenService.removeByMap(ImmutableMap.of("type", CorpWeChatConstants.TOKEN_TYPE_TICKET));
        wechatTokenService.save(wechatToken);
        return wechatToken;
    }

    /**
     * 返回用于企业微信登陆所需要的参数
     *
     * @return cn.hutool.json.JSONObject
     * @author blank
     * @date 2021-3-9 下午 4:39
     */
    @Override
    public JSONObject getCorpWechatLoginParam() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOpt("appid", CorpWeChatProperties.getCorpId());
        jsonObject.putOpt("agentid", CorpWeChatProperties.getCorpAgentId());
        return jsonObject;
    }

    /**
     * 根据code登录 返回对应用户的企业微信ID
     *
     * @param code cdoe
     * @return java.lang.String
     * @author blank
     * @date 2021-3-9 下午 5:07
     */
    @Override
    public String login(@NotNull String code) {

        String token = getAccessToken().getToken();
        return CorpWechatUtil.getScanUserId(CorpWeChatConstants.GET_SCAN_USER_INFO_URL, token, code);
    }

    /**
     * 从企业微信同步所有部门信息
     *
     * @author blank
     * @date 2021-3-9 上午 11:58
     */
    @Override
    public List<UserVO> syncUserOpenIdFormTencent(List<UserVO> userList) {
        try{
            String token = getAddressAccessTokenFromTencent().getToken();
            List<CorpWeChatUserVO> userTencentList = CorpWechatUtil.getUserListUnderDeptFormTencent(CorpWeChatConstants.GET_USER_LIST_URL, token, 1L);
            log.error("syncUserOpenIdFormTencent ------------userTencentList - error = ",userTencentList);
            if (userTencentList != null) {
                for (UserVO user : userList) {
                    for (CorpWeChatUserVO weChatUserVO : userTencentList) {
                        if (StrUtil.isNotBlank(user.getMobile()) && StrUtil.isNotBlank(weChatUserVO.getMobile())) {
                            if (user.getMobile().trim().equals(weChatUserVO.getMobile().trim())) {
                                user.setXworkUserId(weChatUserVO.getUserid());
                                user.setAvatar(weChatUserVO.getAvatar());
                                log.error("syncUserOpenIdFormTencent ------------user - error = ",user);
                            }
                            log.error("syncUserOpenIdFormTencent ------------weChatUserVO - error = ",weChatUserVO);
                        }
                    }
                }
            }
            return userList;
        }catch (Exception e) {
            log.error("syncUserOpenIdFormTencent ------------error = ",e);
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * 向指定用户或部门发送文本信息
     *
     * @param content 内容
     * @param userSet 用户列表
     * @param deptSet 部门列表
     * @return boolean
     * @author blank
     * @date 2021-3-9 下午 3:42
     */
    @Override
    public boolean sendTextMsg(@NotNull String content, Set<String> userSet, Set<Long> deptSet,WechatAppBO wechatApp) {

        String token;
        if (Objects.isNull(wechatApp)) {
            token = this.getAccessToken().getToken();
        } else {
            WechatToken wToken = CorpWechatUtil.getAccessToken(CorpWeChatConstants.GET_ACCESS_TOKEN_URL, wechatApp.getAppId(), wechatApp.getAppSecret());
            if (Objects.isNull(wToken)) {
                log.error("not found wxappid - "+ JSON.toJSONString(wToken));
                return false;
            }
            token = wToken.getToken();
        }

        return CorpWechatUtil.sendTextMsg(CorpWeChatConstants.SEND_MSG_URL, token, CorpWeChatProperties.getCorpAgentId(), content, userSet, deptSet);
    }

    /**
     * 发送卡片消息
     *
     * @param title          卡片标题
     * @param description    卡片内容
     * @param redirectionUrl 点击卡片跳转URL
     * @param userSet        用户列表 企业微信id
     * @param deptSet        部门列表
     * @return boolean
     * @author blank
     * @date 2021-4-14 上午 11:32
     */
    @Override
    public boolean sendTextCardMsg(@NotNull String title, @NotNull String description, @NotNull String redirectionUrl, Set<String> userSet, Set<Long> deptSet) {
        return this.sendTextCardMsgByUserIdByAppCode(title,description,redirectionUrl,userSet,deptSet,null);
    }

//    @Override
//    public boolean sendTextCardMsg(@NotNull String title, @NotNull String description, @NotNull String redirectionUrl, Set<String> userSet, Set<Long> deptSet) {
//        String token = getAccessToken().getToken();
//        return CorpWechatUtil.sendTextCardMsg(CorpWeChatConstants.SEND_MSG_URL, token, corpWeChatProperties.getCorpAgentId(), title, description, redirectionUrl, userSet, deptSet);
//    }

    /**
     * 发送卡片消息
     *
     * @param title          卡片标题
     * @param description    卡片内容
     * @param redirectionUrl 点击卡片跳转URL
     * @param users        用户列表 userId
     * @param deptSet        部门列表
     * @return boolean
     * @author alberttiny
     * @date 2021-10-08 上午 17:32
     */
    @Override
    public boolean sendTextCardMsgByUserId(@NotNull String title, @NotNull String description, @NotNull String redirectionUrl, Set<String> users, Set<Long> deptSet) {

        return this.sendTextCardMsgByUserIdByAppCode(title,description,redirectionUrl,users,deptSet,null);

        //用userId 查询  企业微信 id
//        Set<String> users = userSet.stream().map(String::valueOf).collect(Collectors.toSet());
//        String token = this.getAccessToken().getToken();
//        return CorpWechatUtil.sendTextCardMsg(CorpWeChatConstants.SEND_MSG_URL, token, CorpWeChatProperties.getCorpAgentId(), title, description, redirectionUrl, users, deptSet);
    }

    @Override
    public boolean sendTextCardMsgByUserId(@NotNull String title, @NotNull String description, Set<String> userSet) throws UnsupportedEncodingException {

        String linkUrl = getLinkUrl();
        String redirectUrl = URLEncoder.encode(linkUrl, "UTF-8");
        String url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&agentid={1}&redirect_uri={2}"+"&response_type=code&scope=snsapi_base&state=sp-sales#wechat_redirect";
        url = url.replace("{0}",CorpWeChatProperties.getCorpId())
                .replace("{1}",CorpWeChatProperties.getCorpAgentId()+"")
                .replace("{2}",redirectUrl);
//        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww5323bd8ab4394132&redirect_uri=https://tems.test.storlead.com?&response_type=code&scope=snsapi_base&agentid=1000024&state=aaaaaa#wechat_redirect";

        return this.sendTextCardMsgByUserIdByAppCode(title,description,url,userSet,null,null);
//        return true;
    }

    @Override
    public boolean sendTextCardMsgByUserId(@NotNull String title, @NotNull String description, Set<String> userSet, String router) throws UnsupportedEncodingException {
        try {
            String  linkUrl = getLinkUrl();
            String redirectRouter = StrUtil.isNotBlank(router) ? URLEncoder.encode(router, "UTF-8") : "";
            String redirectlinkUrl = URLEncoder.encode(linkUrl, "UTF-8");
            String url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&agentid={1}&redirect_uri={2}"+"&response_type=code&scope=snsapi_base&state={3}#wechat_redirect";

            url = url.replace("{0}",CorpWeChatProperties.getCorpId())
                    .replace("{1}",CorpWeChatProperties.getCorpAgentId()+"")
                    .replace("{2}",redirectlinkUrl+redirectRouter)
                    .replace("{3}","fromQYwx");
            log.info("消息发送地址："+url);
            return this.sendTextCardMsgByUserIdByAppCode(title,description,url,userSet,null,null);
        } catch (Exception e) {
            log.error("sendTextCardMsgByUserId -- error--",e);
            return false;
        }
    }

    @Override
    public boolean sendTextCardMsgByUserIdByAppCode(@NotNull String title, @NotNull String description, @NotNull String redirectUrl, Set<String> users, Set<Long> deptSet,String appCode) {
        //用userId 查询  企业微信
        try {
            String redirectRouter = "";
            String token;
            if (StrUtil.isBlank(appCode)) {
                token = this.getAccessToken().getToken();
                redirectRouter = redirectUrl;
                return CorpWechatUtil.sendTextCardMsg(CorpWeChatConstants.SEND_MSG_URL, token, CorpWeChatProperties.getCorpAgentId(), title, description, redirectRouter, users, deptSet);
            } else {
                WechatAppBO wechatApp = wechatTokenService.getWechatAppsByAppCode(appCode);
                if (Objects.isNull(wechatApp)) {
                    log.error("not found wechatApp config appCode =  " + appCode);
                    return false;
                }
                WechatToken wToken = CorpWechatUtil.getAccessToken(CorpWeChatConstants.GET_ACCESS_TOKEN_URL, wechatApp.getAppId(), wechatApp.getAppSecret());
                if (Objects.isNull(wToken)) {
                    log.error("not found wxappid = " + JSON.toJSONString(wToken));
                    return false;
                }
                token = wToken.getToken();
                if (StrUtil.isNotBlank(redirectUrl)) {
                    redirectRouter = wechatApp.getHomePage()+"?redirectUrl="+redirectUrl;
                } else {
                    redirectRouter = wechatApp.getHomePage()+"?redirectUrl="+wechatApp.getRedirectUrl();
                }
                return CorpWechatUtil.sendTextCardMsg(CorpWeChatConstants.SEND_MSG_URL, token, Integer.valueOf(wechatApp.getAgentId()), title, description, redirectRouter, users, deptSet);
            }
        } catch (Exception e) {
            log.error("sendTextCardMsgByUserId -- error--",e);
            return false;
        }
    }

    private String getDevUrl(String dev){
        switch (dev){
            case "dev":
                return "https://sales.test.storlead.com";
            case "test":
                return "https://sales.test.storlead.com";
            case "prod":
                return "https://sales.storlead.com";
        }
        return "";
    }
    private String getLinkUrl(){
        return CorpWeChatProperties.getWechatMessageCallbackUrl();
    }
}
