package com.game.business.util.im;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.imsocket.util.ApiResult;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.Deflater;


/**
 * @description: 腾讯im基础配置
 * @author: lilin
 * @date: 2022/5/27 17:32
 */
@Slf4j
public class TencentCloudImUtil {
    private static String HTTPS_URL_PREFIX = "https://adminapisgp.im.qcloud.com/";
    private static String APP_MANAGER = "administrator";
    private static long sdkAppId = 20009542;
    private static String key = "3cc3c3c35228510985ce4a6f1933ee941bbf646fa385d7aee3dd459c531b935a";
    private static final int EXPIRETIME = 30 * 24 * 60 * 60;


    /**
     * 初始化
     *
     * @author lilin
     * @date 2022/5/26 17:16
     */
    public static void init(long sdkAppId, String APP_MANAGER, String key) {
        TencentCloudImUtil.sdkAppId = sdkAppId;
        TencentCloudImUtil.APP_MANAGER = APP_MANAGER;
        TencentCloudImUtil.key = key;
    }

    public static long getSdkAppId(){
        return sdkAppId;
    }


    private static class Base64URL {
        private static byte[] base64EncodeUrl(byte[] input) {
            byte[] base64 = Base64.getEncoder().encode(input);
            for (int i = 0; i < base64.length; ++i){
                switch (base64[i]) {
                    case '+':
                        base64[i] = '*';
                        break;
                    case '/':
                        base64[i] = '-';
                        break;
                    case '=':
                        base64[i] = '_';
                        break;
                    default:
                        break;
                }
            }
            return base64;
        }
    }

    /**
     * 获取腾讯云用户签名
     */
    public static String genUserSig(String userid, byte[] userbuf) {

        long currTime = System.currentTimeMillis() / 1000;

        JSONObject sigDoc = new JSONObject();
        sigDoc.put("TLS.ver", "2.0");
        sigDoc.put("TLS.identifier", userid);
        sigDoc.put("TLS.sdkappid", sdkAppId);
        sigDoc.put("TLS.expire", EXPIRETIME);
        sigDoc.put("TLS.time", currTime);

        String base64UserBuf = null;
        if (null != userbuf) {
            base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
            sigDoc.put("TLS.userbuf", base64UserBuf);
        }
        String sig = hmacsha256(userid, currTime, EXPIRETIME, base64UserBuf);
        if (sig.length() == 0) {
            return "";
        }
        sigDoc.put("TLS.sig", sig);
        Deflater compressor = new Deflater();
        compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
        compressor.finish();
        byte[] compressedBytes = new byte[2048];
        int compressedBytesLength = compressor.deflate(compressedBytes);
        compressor.end();
        return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
                0, compressedBytesLength)))).replaceAll("\\s*", "");
    }


    private static String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
        String contentToBeSigned = "TLS.identifier:" + identifier + "\n"
                + "TLS.sdkappid:" + sdkAppId + "\n"
                + "TLS.time:" + currTime + "\n"
                + "TLS.expire:" + expire + "\n";
        if (null != base64Userbuf) {
            contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
        }
        try {
            byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
            Mac hmac = Mac.getInstance("HmacSHA256");
            SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
            hmac.init(keySpec);
            byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
            return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            return "";
        }
    }


    /**
     * 获取腾讯im请求路径
     */
    private static String getHttpsUrl(String imServiceApi, Integer random) {
        return String.format("%s%s?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json",
                HTTPS_URL_PREFIX, imServiceApi, sdkAppId, APP_MANAGER, genUserSig("administrator", null), random);
    }

    /**
     * 导入单个账号
     * @param userId 用户id
     */
    public static void accountImport(String userId) {
        accountImport(userId, null);
    }

    public static void accountImport(String userId, String userName) {
        accountImport(userId, userName, null);
    }

    public static void accountImport(String userId, String userName, String faceUrl) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.ACCOUNT_IMPORT, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("UserID", userId);
        if (StringUtils.isNotEmpty(userName)) {
            jsonObject.put("Nick", userName);
        }
        if (StringUtils.isNotEmpty(faceUrl)) {
            jsonObject.put("FaceUrl", faceUrl);
        }
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }

    /**
     * 导入多个账号
     * @param userIds 用户id集合
     */
    public static void multiAccountImport(List<String> userIds) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.MULTI_ACCOUNT_IMPORT, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("Accounts", userIds);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }

    /**
     * 删除账号
     * @param userIds 用户id集合
     */
    public static void accountDelete(List<String> userIds) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.ACCOUNT_DELETE, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("DeleteItem", getUserIdJsonList(userIds));
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }


    /**
     * 查询帐号在线状态
     * @param userId 用户id集合
     */
    public static boolean queryOnlineStatus(String userId) {
        boolean isOnline = false;
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.ACCOUNT_QUERY_STATE, random);
        JSONObject jsonObject = new JSONObject();
        List<String> list = new ArrayList<>();
        list.add(userId);
        jsonObject.put("To_Account", list);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
        if("OK".equals(JSONObject.parseObject(result).get("ActionStatus"))){
            JSONArray jsonArray = JSONObject.parseObject(result).getJSONArray("QueryResult");
            JSONObject jb = (JSONObject)jsonArray.get(0);
            if("Online".equals(jb.getString("Status"))){
                isOnline = true;
            }
        }
        return isOnline;
    }



    private static List<JSONObject> getUserIdJsonList(List<String> userIds) {
        return userIds.stream().map(v -> {
            JSONObject userIdJson = new JSONObject();
            userIdJson.put("UserID", v);
            return userIdJson;
        }).collect(Collectors.toList());
    }


    /**
     * 单发单聊消息
     * @param syncOtherMachine 是否同步消息到发送方（1-同步，2-不同步）
     * @param fromUserId 发送方用户id (默认adminstrator, 给null)
     * @param toUserId 接收方用户id
     * @param msgContent 消息内容
     * @param msgLifeTime 消息保存时间，-1表示默认（7天）
     */
    public static String sendMsg(Integer syncOtherMachine, String fromUserId, String toUserId, String msgContent, int msgLifeTime) {
        if(StringUtils.isEmpty(fromUserId)){
            fromUserId = "administrator";
        }

        if(sdkAppId > 0){
            Integer random = RandomUtils.nextInt(0, 999999999);
            String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.SEND_MSG, random);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("SyncOtherMachine", syncOtherMachine);
            if (StringUtils.isNotEmpty(fromUserId)) {
                // 发送方不为空表示指定发送用户，为空表示为管理员发送消息
                jsonObject.put("From_Account", fromUserId);
            }
            if(msgLifeTime == -1){
                msgLifeTime = 604800;
            }
            jsonObject.put("MsgLifeTime", msgLifeTime);
            jsonObject.put("To_Account", toUserId);
            jsonObject.put("MsgRandom", random);
            List<JSONObject> msgBody = getMsgBody(TencentCloudImConstant.TIM_CUSTOM_ELEM, msgContent);
            jsonObject.put("MsgBody", msgBody);
            String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
            System.out.println("单发结果："+ result.toString());
            return result;
        }

        return null;
    }


    /**
     * 拼接发送消息内容
     * @param msgType 消息类型
     * @param msgContent 发送消息内容
     * @return 消息内容
     */
    private static List<JSONObject> getMsgBody(String msgType, String msgContent) {
        List<JSONObject> msgBody = new ArrayList<>();
        if (msgType.equals(TencentCloudImConstant.TIM_CUSTOM_ELEM)) {
            // 文本类型
            JSONObject msgBodyJson = new JSONObject();
            msgBodyJson.put("MsgType", msgType);

            JSONObject contentJson = new JSONObject();
            contentJson.put("Data", msgContent);

            msgBodyJson.put("MsgContent", contentJson);
            msgBody.add(msgBodyJson);
        }
        return msgBody;
    }


    /**
     * 腾讯云im创建群聊
     * @param type 群组类型：Private/Public/ChatRoom/AVChatRoom/Community（必填）
     * @param ownerUserId 群主
     * @param groupId 群聊id
     * @param groupName 群聊名称
     *
     */
    public static ApiResult createGroup(String type, String ownerUserId, String groupId, String groupName) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.CREATE_GROUP, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("Owner_Account", ownerUserId);
        jsonObject.put("Type", type);
        jsonObject.put("Name", groupName);
        jsonObject.put("GroupId", groupId);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
        JSONObject resultJson = JSONObject.parseObject(result);
        if("OK".equals((String)resultJson.get("ActionStatus"))){
            return new ApiResult(1, "创建成功");
        }else {
            return new ApiResult((Integer)resultJson.get("ErrorCode"), (String)resultJson.get("ErrorInfo"));
        }
    }


    /**
     * 腾讯云im解散群组
     * @param groupId 群聊id
     *
     */
    public static void destroyGroup(String groupId) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.DESTROY_GROUP, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("GroupId", groupId);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }


    /**
     * 加入群聊
     * @param groupId 群id
     * @param userid 加入群聊用户id
     */
    public static void addGroupMember(String groupId, String userid){
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.ADD_GROUP_MEMBER, random);
        List<Map> mapList = new ArrayList<>();
        Map map = new HashMap();
        map.put("Member_Account", userid);
        mapList.add(map);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("GroupId", groupId);
        jsonObject.put("MemberList", mapList);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }

    /**
     * 删除群成员
     * @param groupId 群id
     * @param userid 加入群聊用户id
     * @param silence 0.非静默删除  1.静默删除
     */
    public static void delGroupMember(String groupId, String userid, int silence){
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.DELETE_GROUP_MEMBER, random);
        List<String> accountList = new ArrayList<>();
        accountList.add(userid);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("GroupId", groupId);
        jsonObject.put("Silence", silence);
        jsonObject.put("MemberToDel_Account", accountList);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }


    /**
     * 在群组中发送系统通知
     * @param groupId 群id
     * @param Content 通知内容
     */
    public static void sendGroupSystemNotification(String groupId, String Content){
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.SEND_GROUP_SYSTEM_NOTIFICATION, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("GroupId", groupId);
        jsonObject.put("Content", Content);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
    }


    /***
     * 在群组中发送普通消息
     * @param GroupId 群组id
     * @param fromUserId 发送者id
     * @param msgContent 消息内容
     * @param onlineOnlyFlag 1表示消息仅发送在线成员，默认0表示发送所有成员，AVChatRoom(直播群)不支持该参数，-1表示此参数无效（用于直播群）
     */
    public static String sendGroupMsg(String GroupId, String fromUserId, String msgContent, int onlineOnlyFlag) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.SEND_GROUP_MSG, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("GroupId", GroupId);
        jsonObject.put("Random", random);
        if(onlineOnlyFlag != -1){
            jsonObject.put("OnlineOnlyFlag", onlineOnlyFlag);
        }
        if (StringUtils.isNotEmpty(fromUserId)) {
            // 发送方不为空表示指定发送用户，为空表示为管理员发送消息
            jsonObject.put("From_Account", fromUserId);
        }
        List<JSONObject> msgBody = getMsgBody(TencentCloudImConstant.TIM_CUSTOM_ELEM, msgContent);
        jsonObject.put("MsgBody", msgBody);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
        return result;
    }


    /**
     * 获取用户所加入的群组
     * @param userId 用户id
     * @param type 群聊类型
     */
    public static JSONArray getJoinedGroupList(String userId, String type){
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.GET_JOINED_GROUP_LIST, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("Member_Account", userId);
        jsonObject.put("GroupType", type);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
        JSONArray jsonArray = new JSONArray();
        if("OK".equals(JSONObject.parseObject(result).get("ActionStatus"))){
            jsonArray = JSONObject.parseObject(result).getJSONArray("GroupIdList");
        }
        return jsonArray;
    }


    /**
     * 获取群详细资料
     * @param groupIdList 群id数组
     */
    public static JSONObject getGroupInfo(List<String> groupIdList){
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.GET_GROUP_INFO, random);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("GroupIdList", groupIdList);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
        JSONObject resultJson = JSONObject.parseObject(result);
        return resultJson;
    }

    /**
     * 判断群是否被创建过
     * @param groupId 群id
     */
    public static boolean haveGroup(String groupId){
        List<String> stringList = new ArrayList<>();
        stringList.add(groupId);
        JSONObject jsonObject = getGroupInfo(stringList);
        JSONObject groupInfo = (JSONObject)jsonObject.getJSONArray("GroupInfo").get(0);
        Integer errorCode = (Integer) groupInfo.get("ErrorCode");
        if(errorCode == 0){
            return true;
        }else {
            return false;
        }
    }


    /**
     * 直播群广播消息
     */
    public static String imAllGroupPush(String msgContent) {
        if(sdkAppId > 0){
            Integer random = RandomUtils.nextInt(0, 999999999);
            String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AllPushManage.IM_ALL_GROUP_MSG, random);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("From_Account", "administrator");
            jsonObject.put("Random", random);

            List<JSONObject> msgBody = getMsgBody(TencentCloudImConstant.TIM_CUSTOM_ELEM, msgContent);
            jsonObject.put("MsgBody", msgBody);
            String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
            return result;
        }
        return null;
    }


    /***
     * 批量发送单聊消息,一次500人上限
     * @param msgContent 消息内容
     */
    public static String imPushBatchSendMsg(List<String> userIdList, String msgContent) {
        if(sdkAppId > 0){
            log.info("调用IM接口，IM_PUSH, msgContent:{}", msgContent);
            Integer random = RandomUtils.nextInt(0, 999999999);
            String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.BATCH_SEND_MSG, random);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("SyncOtherMachine", 2);  // 消息不同步至发送方
            jsonObject.put("From_Account", "administrator");
            JSONArray jsonArray = new JSONArray();
            for (String s : userIdList) {
                jsonArray.add(s);
            }
            jsonObject.put("To_Account", jsonArray);
            jsonObject.put("MsgRandom", random);
            jsonObject.put("MsgLifeTime", 0);
            List<JSONObject> msgBody = getMsgBody(TencentCloudImConstant.TIM_CUSTOM_ELEM, msgContent);
            jsonObject.put("MsgBody", msgBody);
            log.info("发起请求，request:{}", jsonObject);
            String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
            log.info("imPushBatchSendMsg result: {}", result);
            return result;
        }
        return null;
    }

    /***
     * 全员推送
     * @param msgContent 消息内容
     */
    public static String imPush(String msgContent) {
        if(sdkAppId > 0){
            log.info("调用IM接口，IM_PUSH, msgContent:{}", msgContent);
            Integer random = RandomUtils.nextInt(0, 999999999);
            String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AllPushManage.IM_PUSH, random);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("From_Account", "administrator");
            jsonObject.put("MsgRandom", random);
            jsonObject.put("MsgLifeTime", 0);

            List<JSONObject> msgBody = getMsgBody(TencentCloudImConstant.TIM_CUSTOM_ELEM, msgContent);
            jsonObject.put("MsgBody", msgBody);
            String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);
            log.info("IM_PUSH result: {}", result);
            return result;
        }
        return null;
    }



    /***
     * 拉取运营数据
     * @param requestField 指定需要拉取的字段
     */
    public static Object getAppInfo(String requestField) {
        Integer random = RandomUtils.nextInt(0, 999999999);
        String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.OperationManage.GET_APP_INFO, random);
        JSONObject jsonObject = new JSONObject();
        List<String> list = new ArrayList<>();
        list.add(requestField);
        jsonObject.put("RequestField", list);
        String result = HttpClientUtils.JSONObjectPost(httpsUrl, jsonObject);

        if((Integer) JSONObject.parseObject(result).get("ErrorCode") == 0){
            JSONArray jsonArray = (JSONArray)JSONObject.parseObject(result).get("Result");
            JSONObject jb = (JSONObject)jsonArray.get(0);
            return jb.get(requestField);
        }
        return null;
    }

//    public static void main(String[] args) {
//        JSONObject paramJson = new JSONObject();
//        paramJson.put("type", "UserSystemNotify");
//        paramJson.put("subType", "UserRefreshBalance");
//        paramJson.put("content", JSONObject.parseObject("{'msg':'刷新余额'}"));
//        List<String> userIdList = new ArrayList<>();
//        userIdList.add("10133");
//        TencentCloudImUtil.imPushBatchSendMsg(userIdList, paramJson.toString());
//    }
}
