package cn.iocoder.yudao.module.system.api.open;

import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.string.StringUtil;
import cn.iocoder.yudao.framework.common.util.time.TimeUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.api.open.dto.OpenAccessToken;
import cn.iocoder.yudao.module.system.api.open.dto.OpenAccessTokenResponse;
import cn.iocoder.yudao.module.system.api.open.dto.OpenAddress;
import cn.iocoder.yudao.module.system.api.open.dto.OpenAddressResponse;
import cn.iocoder.yudao.module.system.api.wechat.CorpWechatApi;
import cn.iocoder.yudao.module.system.api.wechat.dto.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.WechatMessageDO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.WechatMessageMapper;
import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import cn.iocoder.yudao.module.system.util.http.HttpClientResult;
import cn.iocoder.yudao.module.system.util.http.HttpClientUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO.PACKAGE_ID_SYSTEM;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.oauth2.EnterpriseWeChatConstants.*;
import static cn.iocoder.yudao.module.system.enums.open.OpenConstants.*;

/**
 * @Author: jinyd
 * @CreateTime: 2024/11/27  8:53
 * @Description:
 * @Version: 4.0
 */

@Service
@Slf4j
public class OpenApiImpl implements OpenApi {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SocialClientMapper socialClientMapper;

    @Override
    @TenantIgnore
    public String getOpenAccessToken(Long tenantId) {

        String accessToken = "";
        String rKey = String.format(openKey, tenantId);
        log.info("getOpenAccessToken key:" + rKey);
        Object reddisValue = stringRedisTemplate.opsForValue().get(rKey);
        if (reddisValue != null){
            accessToken = reddisValue.toString();
            log.info("getOpenAccessToken accessToken:" + accessToken);
        }
        if (StringUtil.isEmptyORNull(accessToken)) {
            String url = GET_ACCESS_TOKEN_URL;
            Map<String, String> map = new HashMap<>();
            map.put("appKey", APP_KEY);
            map.put("appSecret", APP_SECRET);
            try{
                HttpClientResult httpClientResult = HttpClientUtil.doPost(url, map, null);
                String content = httpClientResult.getContent();
                log.info("getOpenAccessToken content:" + content);


                OpenAccessTokenResponse response = JSON.parseObject(content, OpenAccessTokenResponse.class);
                if (response.getCode() == 200) {
                    OpenAccessToken data = response.getData();
                    log.info("getOpenAccessToken data.getAccessToken():" + data.getAccessToken());
                    stringRedisTemplate.opsForValue().set(rKey, data.getAccessToken(), data.getExpireTime() - TimeUtil.ONE_MINUTE, TimeUnit.SECONDS);
                    accessToken = data.getAccessToken();
                }
            } catch (Exception e) {
                log.error("获取开放平台AccessToken发生错误: ", e);
            }

        }
        return accessToken;
    }

    @Override
    public String getOpenAddress(Long tenantId) {
        SocialClientDO client = socialClientMapper.selectOne(SocialTypeEnum.OPEN_YS7.getType(), UserTypeEnum.ADMIN.getValue(), tenantId);
        Assert.notNull(client, String.format("第三方(%d) 不存在", SocialTypeEnum.OPEN_YS7.getType()));
        String accessToken = getOpenAccessToken(tenantId);
        Assert.notNull(accessToken, "获取开放平台token为空，请联系管理员");
        String url = GET_ADDRESS_URL;
        Map<String, String> map = new HashMap<>();
        map.put("accessToken", accessToken);
        map.put("deviceSerial", client.getAgentId());
        try{
            HttpClientResult httpClientResult = HttpClientUtil.doPost(url, map, null);
            String content = httpClientResult.getContent();
            log.info("getOpenAddress content:" + content);

            OpenAddressResponse response = JSON.parseObject(content, OpenAddressResponse.class);
            if (response.getCode() == 200) {
                OpenAddress data = response.getData();
                log.info("getOpenAddress data.getUrl():" + data.getUrl());
                return data.getUrl();
            }
        } catch (Exception e) {
            log.error("开放平台getOpenAddress发生错误: ", e);
        }
        return null;
    }

    

}
