package com.gic.haoban.manage.web.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ctrip.framework.apollo.ConfigService;
import com.gic.api.base.commons.Page;
import com.gic.commons.util.HttpClient;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.common.utils.EntityUtil;
import com.gic.haoban.common.utils.HaobanResponse;
import com.gic.haoban.manage.api.dto.*;
import com.gic.haoban.manage.api.service.*;
import com.gic.haoban.manage.api.service.hm.HmQrcodeApiService;
import com.gic.haoban.manage.web.config.Config;
import com.gic.haoban.manage.web.errCode.HaoBanErrCode;
import com.gic.haoban.manage.web.qo.QywxXcxSendMessageQo;
import com.gic.redis.data.util.GicRateLimiter;
import com.gic.redis.data.util.RedisUtil;
import com.gic.wechat.api.dto.qywx.QywxNewUseridDTO;
import com.gic.wechat.api.dto.qywx.QywxXcxSendMessageDTO;
import com.gic.wechat.api.service.qywx.QywxCorpApiService;
import com.gic.wechat.api.service.qywx.QywxSuiteApiService;
import com.gic.wechat.api.service.qywx.QywxUserApiService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created 2020/4/9.
 *
 * @author hua
 */
@RestController
@RequestMapping("/test")
public class TestController extends WebBaseController {


    private static final Logger logger = LoggerFactory.getLogger(TestController.class);

    private final ExecutorService pools = Executors.newFixedThreadPool(500);

    @Autowired
    private QywxSuiteApiService qywxSuiteApiService;
    @Autowired
    private TestApiService testApiService;
    @Autowired
    private MaidianLogApiService maidianLogApiService;
    @Autowired
    private WxEnterpriseRelatedApiService wxEnterpriseRelatedApiService;
    @Autowired
    private WxEnterpriseApiService wxEnterpriseApiService;
    @Autowired
    private QywxUserApiService qywxUserApiService;
    @Autowired
    private StaffApiService staffApiService;
    @Autowired
    private WxApplicationApiService wxApplicationApiService;
    @Autowired
    private Config config;
    @Autowired
    private HmQrcodeApiService hmQrcodeApiService;
    @Autowired
    private QywxCorpApiService qywxCorpApiService;
    @Autowired
    private QwFriendApiService qwFriendApiService ;
    
    
    @RequestMapping("/qwcode")
    public HaobanResponse qwcode(String enterpriseId, String unionid,String openid,String wxaUnionid ,String code) {
        return this.resultResponse(HaoBanErrCode.ERR_0,code);
    }
    
    @RequestMapping("/pending-check")
    public HaobanResponse pendingChec(String enterpriseId, String unionid,String openid,String wxaUnionid ,String wxaOpenid) {
        return this.resultResponse(HaoBanErrCode.ERR_0,this.qwFriendApiService.pendingIdCheck(enterpriseId, unionid, openid, wxaUnionid,wxaOpenid));
    }
    
    @RequestMapping("/get-pending-times")
    public HaobanResponse getTestTimes(String wxEnterpriseId) {
        return this.resultResponse(HaoBanErrCode.ERR_0,this.qwFriendApiService.getCallTimes(wxEnterpriseId));
    }

    @RequestMapping("/send-message-test")
    public HaobanResponse testSendMessage(QywxXcxSendMessageQo qo) {
        QywxXcxSendMessageDTO messageDTO = EntityUtil.changeEntityByOrika(QywxXcxSendMessageDTO.class, qo);
        ArrayList<String> list = new ArrayList<>();
        list.add(qo.getUserId());

        messageDTO.setUserIds(list);
        boolean b = qywxSuiteApiService.sendMessage("ww9ede832a84b7ae5f",
                "ww2c34dc56739bb105", messageDTO);
        if (b) {
            return resultResponse(HaoBanErrCode.ERR_1);
        } else {
            return resultResponse(HaoBanErrCode.ERR_0);
        }
    }


    @RequestMapping("/test-dubbo")
    public HaobanResponse dubbo(@RequestParam(defaultValue = "2000") Integer n, @RequestParam(defaultValue = "100") String t) {
        int i = n;
        while (i-- > 0) {
            int finalI = i;
            pools.execute(new Runnable() {
                @Override
                public void run() {
                    long start = System.currentTimeMillis();
                    testApiService.checkThread(finalI + "", Long.valueOf(t));
                    logger.info("时间:{}", System.currentTimeMillis() - start);
                }
            });
        }
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    @RequestMapping("/lock")
    public HaobanResponse lock(String name, Long time, int ty) {
        RedisUtil.lock(name, time, TimeUnit.SECONDS, 0L);
        if (ty == 0) {
            if (RedisUtil.isLocked(name)) {
                RedisUtil.unlock(name);
            }
        }
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    @RequestMapping("/maidian-log")
    public HaobanResponse maidian(String hbversion, BasePageInfo pageInfo) {
        Page<MaidianLogDTO> page = maidianLogApiService.queryList(hbversion, pageInfo);
        return resultResponse(HaoBanErrCode.ERR_1, page);
    }

    @RequestMapping("/deal-slef-qywx-sys-department")
    public HaobanResponse dealSys1(String corpid, String secretVal, String dataId) {
        testApiService.listSelfQywxUser(corpid, secretVal, dataId);
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    @RequestMapping("/deal-all-qywx-sys-department")
    public HaobanResponse dealSys2(String corpid, String secretVal, String dataId) {
        testApiService.listAllQywxUser(corpid, secretVal, dataId);
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    @RequestMapping("/test-limiter")
    public HaobanResponse testLimiter(String key, String eid) {
        if (StringUtils.isAnyBlank(key, eid)) {
            return resultResponse(HaoBanErrCode.ERR_5);
        }
        GicRateLimiter instance = GicRateLimiter.getInstance("haoban-manage3-web");
        Long acquire = instance.acquire(key, eid);
        if (acquire == 0L) {
            return resultResponse(HaoBanErrCode.ERR_13);
        }
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    @RequestMapping("/init-history")
    public HaobanResponse initHistory(String wxEnterpriseId) {
        wxEnterpriseRelatedApiService.initHistoryEnterprise(wxEnterpriseId);
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    /**
     * 获取到分表到哪个表内
     *
     * @param tableId 分表id
     * @param count   分表数量
     * @return
     */
    @RequestMapping("/test-table")
    public HaobanResponse testTable(String tableId, Integer count) {
        if (StringUtils.isBlank(tableId)) {
            return resultResponse(HaoBanErrCode.ERR_5);
        }
        if (count == null) {
            return resultResponse(HaoBanErrCode.ERR_5);
        }
        int i = tableId.hashCode() % count;
        return resultResponse(HaoBanErrCode.ERR_1, i);
    }

    /**
     * 设置迁移完成
     *
     * @param corpid
     * @param serviceCorpid
     * @return
     */
    @RequestMapping("/finishExternalUseridMigration")
    public HaobanResponse finishExternalUseridMigration(String corpid, String serviceCorpid) {
        boolean flag = qywxUserApiService.finishExternalUseridMigration(corpid, serviceCorpid);
        if (flag) {
            WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseApiService.getEnterpriseBycorpId(corpid);
            if (wxEnterpriseDTO == null) {
                return resultResponse(HaoBanErrCode.ERR_10012);
            }
            wxEnterpriseApiService.agreeExternalUseridFlag(wxEnterpriseDTO.getWxEnterpriseId(), 1);
            return resultResponse(HaoBanErrCode.ERR_1);
        } else {
            return resultResponse(HaoBanErrCode.ERR_0);
        }
    }

    /**
     * 测试授权回调
     *
     * @param param
     * @return
     */
    @RequestMapping("/callbackReviceEnterprise")
    public HaobanResponse callbackReviceEnterprise(String param) {
        QywxCorpInfoSimpleDTO qywxCorpInfoSimpleDTO = JSON.parseObject(param, QywxCorpInfoSimpleDTO.class);
        wxEnterpriseApiService.callbackReviceEnterprise(qywxCorpInfoSimpleDTO);
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    /**
     * 后台预留批量处理wx_user_id to wx_open_user_id
     *
     * @param corpid
     * @return
     */
    @RequestMapping("/useridToOpenuserid")
    public HaobanResponse useridToOpenuserid(String corpid) {
        WxApplicationDTO wxApplicationDTO = wxApplicationApiService.selectByCorpid(corpid);
        String wxEnterpriseId = wxApplicationDTO.getWxEnterpriseId();
        String siteId = wxApplicationDTO.getSiteId();
        // 限流器
        RRateLimiter rateLimiter = RedisUtil.getRedisClient().getRateLimiter("haoban:manage3:updateWxOpenUserId:limit");
        // 每1秒产生5个令牌
        rateLimiter.trySetRate(RateType.OVERALL, 5, 1, RateIntervalUnit.SECONDS);
        int pageNum = 1;
        while (true) {
            rateLimiter.acquire();
            //批量处理wx_user_id to wx_open_user_id
            Page<StaffDTO> staffDTOPageInfo = staffApiService.listUserIdByWxEnterpriseId(wxEnterpriseId, pageNum, 1000);
            List<StaffDTO> staffDTOS = staffDTOPageInfo.getResult();
            if (CollectionUtils.isEmpty(staffDTOS)) {
                break;
            }
            pageNum++;
            logger.info("useridToOpenuserid请求：corpid：{}", corpid);
            List<QywxNewUseridDTO> qywxNewUseridDTOS = qywxUserApiService.useridToOpenuserid(corpid, siteId, staffDTOS.stream().map(StaffDTO::getWxUserId).collect(Collectors.toList()));
            if (CollectionUtils.isNotEmpty(qywxNewUseridDTOS)) {
                for (QywxNewUseridDTO qywxNewUseridDTO : qywxNewUseridDTOS) {
                    staffApiService.updateOpenUserIdsByUserId(wxEnterpriseId, qywxNewUseridDTO.getUserid(), qywxNewUseridDTO.getOpen_userid());
                }
            }
        }
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    /**
     * 后台单个处理wx_user_id to wx_open_user_id
     *
     * @param corpid
     * @param staffId
     * @return
     */
    @RequestMapping("/useridToOpenuseridByStaffId")
    public HaobanResponse useridToOpenuseridByStaffId(String corpid, String staffId) {
        StaffDTO staffDTO = staffApiService.selectById(staffId);
        if (staffDTO == null) {
            return resultResponse(HaoBanErrCode.ERR_8);
        }
        String wxUserId = staffDTO.getWxUserId();
        String openUserid = getOpenUserid(wxUserId, corpid);
        staffApiService.updateOpenUserIdsByUserId(staffDTO.getWxEnterpriseId(), wxUserId, openUserid);
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    /**
     * 获取openuserid
     *
     * @param userId
     * @param corpid
     * @return
     */
    private String getOpenUserid(String userId, String corpid) {
        WxApplicationDTO wxApplicationDTO = wxApplicationApiService.selectByCorpid(corpid);
        List<QywxNewUseridDTO> qywxNewUseridDTOS = qywxUserApiService.useridToOpenuserid(corpid, wxApplicationDTO.getSiteId(), Collections.singletonList(userId));
        if (CollectionUtils.isEmpty(qywxNewUseridDTOS)) {
            return "";
        }
        return qywxNewUseridDTOS.get(0).getOpen_userid();
    }

    /**
     * 代开发完成升级
     * @param corpid
     * @param agentid
     * @param openidType
     * @return
     */
    @RequestMapping("/finishOpenidMigration")
    public HaobanResponse finishOpenidMigration(String corpid, String agentid, String openidType) {
        String[] openidTypeSplit = openidType.split(",");
        boolean flag = qywxUserApiService.finishOpenidMigration(corpid, config.getCorpid(), agentid, openidTypeSplit);
        return resultResponse(HaoBanErrCode.ERR_1, flag);
    }

    /**
     * 转自建userid
     * @param corpid
     * @param secret
     * @param userIds
     * @return
     */
    @RequestMapping("/getSelfUseridToOpenuserid")
    public HaobanResponse getSelfUseridToOpenuserid(String corpid, String secret, String userIds) {
        String[] split = userIds.split(",");
        List<QywxNewUseridDTO> list = qywxUserApiService.getSelfUseridToOpenuserid(corpid, secret, Arrays.asList(split));
        return resultResponse(HaoBanErrCode.ERR_1, list);
    }

    /**
     * 生成活码
     * @return
     */
    @RequestMapping("/checkStaffOpenContact")
    public HaobanResponse checkStaffOpenContact() {
        hmQrcodeApiService.checkStaffOpenContact("-1");
        return resultResponse(HaoBanErrCode.ERR_1);
    }

    /**
     * 生成活码单企业
     * @param wxEnterpriseId
     * @param enterpriseId
     * @return
     */
    @RequestMapping("/checkStaffOpenContactByWxEnterpriseId")
    public HaobanResponse checkStaffOpenContactByWxEnterpriseId(String wxEnterpriseId,String enterpriseId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("wxEnterpriseId",wxEnterpriseId);
        jsonObject.put("enterpriseId",enterpriseId);
        hmQrcodeApiService.checkStaffOpenContactByWxEnterpriseId(jsonObject.toJSONString());
        return resultResponse(HaoBanErrCode.ERR_1);
    }
    
    
    @RequestMapping("test-qw-post-fws")
    public HaobanResponse testQwPost(String url , String corpid , String json) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getProviderAccessToken(corpid) ;
        logger.info("toekn={},corpId={} , url={} , json={}",token, corpid ,(url + token) , json);
        Map<String, Object> map = HttpClient.getWinxinResByJson(url + token ,json);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    @RequestMapping("test-qw-get-fws")
    public HaobanResponse testQwGet(String url , String corpId) {
        if(isProd()) {
            return null ;
        }
        String token =qywxCorpApiService.getProviderAccessToken(corpId) ;
        logger.info("toekn={},appid={} , url={} , json={}",token,corpId ,(url + token));
        Map<String, Object> map = HttpClient.getHttpByGet(url + token);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    
    @RequestMapping("test-qw-post-3")
    public HaobanResponse testQwPost3(String url , String corpid , String json) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getCorpAccessToken(corpid,config.getWxSuiteid()) ;
        logger.info("toekn={},corpId={} , url={} , json={}",token, corpid ,(url + token) , json);
        Map<String, Object> map = HttpClient.getWinxinResByJson(url + token ,json);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    
    @RequestMapping("test-qw-post-suite")
    public HaobanResponse testQwPostSuite(String url , String corpid , String json) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getSuiteAccessToken(config.getWxSuiteid()) ;
        logger.info("toekn={},corpId={} , url={} , json={}",token, corpid ,(url + token) , json);
        Map<String, Object> map = HttpClient.getWinxinResByJson(url + token ,json);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    
    @RequestMapping("test-qw-token")
    public HaobanResponse testQwPost3(String corpid ,  String secret) {
        if(StringUtils.isBlank(secret)) {
            String token = qywxCorpApiService.getCorpAccessToken(corpid,config.getWxSuiteid()) ;
            return resultResponse(HaoBanErrCode.ERR_0, token) ;
        }else {
            String token = qywxCorpApiService.getToken(corpid, secret) ;
            return resultResponse(HaoBanErrCode.ERR_0, token) ;
        }
    }
    
    @RequestMapping("test-qw-get-3")
    public HaobanResponse testQwGet3(String url , String corpid) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getCorpAccessToken(corpid,config.getWxSuiteid()) ;
        logger.info("toekn={},appid={} , url={} , json={}",token,corpid ,(url + token));
        Map<String, Object> map = HttpClient.getHttpByGet(url + token);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    
    @RequestMapping("test-qw-get-suite")
    public HaobanResponse testQwGetSuite(String url , String corpid) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getSuiteAccessToken(config.getWxSuiteid()) ;
        logger.info("toekn={},appid={} , url={} , json={}",token,corpid ,(url + token));
        Map<String, Object> map = HttpClient.getHttpByGet(url + token);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    @RequestMapping("test-qw-post-dk")
    public HaobanResponse testQwPostdk(String url , String corpid , String secret, String json) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getToken(corpid, secret) ;
        logger.info("toekn={},corpId={} , url={} , json={}",token, corpid ,(url + token) , json);
        Map<String, Object> map = HttpClient.getWinxinResByJson(url + token ,json);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    @RequestMapping("test-qw-get-dk")
    public HaobanResponse testQwGetdk(String url , String corpid , String secret) {
        if(isProd()) {
            return null ;
        }
        String token = qywxCorpApiService.getToken(corpid, secret) ;
        logger.info("toekn={},appid={} , url={} , json={}",token,corpid ,(url + token));
        Map<String, Object> map = HttpClient.getHttpByGet(url + token);
        return resultResponse(HaoBanErrCode.ERR_0, map) ;
    }
    
    private boolean isProd() {
        com.ctrip.framework.apollo.Config config =  ConfigService.getConfig("COMMON.gic-properties");
        String env = config.getProperty("environment.value", "");
        boolean isProd = "prod".equals(env);
        return false ;
    }
    
    @RequestMapping("test-get-qwinfo")
    public Object getQwInfo(String wxEnterpriseId) {
        if(StringUtils.isEmpty(wxEnterpriseId)) {
            return "参数无" ;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseApiService.getQwInfo(wxEnterpriseId) ;
        if(null == qwDTO) {
            return "企业不存在" ;
        }
        Map<String,Object> map = new HashMap<>();
        map.put("企微加密说明", "1(全明文) 2(全密文) 3(第三方密文，代开明文) 4(第三方明文，代开密文)") ;
        map.put("当前企业加密方式", getCorpid(qwDTO)) ;
        map.put("企微信息", qwDTO) ;
        
        return map ;
    }
    
    
    private String getCorpid(WxEnterpriseQwDTO wxEnterpriseDTO) {
        int wxType =  wxEnterpriseDTO.getWxSecurityType() ;
        String desc = " -- " ;
        if(wxType==1) {
            desc = "（全部明文）" ;
        }
        if(wxType==2) {
            desc =  "（全部密文）" ;
        }
        if(wxType==3) {
            desc =  "（第三方密文，代开明文）" ;
        }
        if(wxType==4) {
            desc =  "（第三方明文，代开密文）" ;
        }
        return Arrays.asList(wxEnterpriseDTO.getThirdCorpid()+"(第三方)",wxEnterpriseDTO.getDkCorpid()+"(代开发)").stream().filter(str ->  StringUtils.isNotBlank(str)).collect(Collectors.joining(" / ")) + desc;
    }
    
}
