package com.qmth.themis.business.util;

import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.domain.TencentYunDomain;
import com.qmth.themis.business.entity.TOeExamRecord;
import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
import com.qmth.themis.business.service.TGErrorService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.trtc.v20190722.TrtcClient;
import com.tencentcloudapi.trtc.v20190722.models.DismissRoomByStrRoomIdRequest;
import com.tencentcloudapi.trtc.v20190722.models.DismissRoomByStrRoomIdResponse;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaResponse;
import com.tencentyun.TLSSigAPIv2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Description: 腾讯云util
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/8/21
 */
@Component
public class TencentYunUtil {
    private final static Logger log = LoggerFactory.getLogger(TencentYunUtil.class);

    @Resource
    RedisUtil redisUtil;

    @Resource
    TGErrorService tgErrorService;

    @Resource
    MonitorUtil monitorUtil;

    private TencentYunDomain tencentYunDomain;

    @Bean
    public TencentYunDomain tencentYunEnv(TencentYunDomain tencentYunDomain) {
        this.tencentYunDomain = new TencentYunDomain(tencentYunDomain.getAppId(),
                tencentYunDomain.getKey(),
                tencentYunDomain.getUrls(),
                tencentYunDomain.getQueryUrl(),
                tencentYunDomain.getService(),
                tencentYunDomain.getSecretId(),
                tencentYunDomain.getSecretKey(),
                tencentYunDomain.getVodAppId(),
                tencentYunDomain.getCallbackPwd(),
                tencentYunDomain.getCallbackTime(),
                tencentYunDomain.getTrtcQueryUrl(),
                tencentYunDomain.getTrtcRegion());
        return this.tencentYunDomain;
    }

    /**
     * 获取签名
     *
     * @param sessionId
     * @param expireTime
     * @return
     */
    public String getSign(String sessionId, Long expireTime) {
        TLSSigAPIv2 api = new TLSSigAPIv2(Long.parseLong(this.tencentYunDomain.getAppId()), this.tencentYunDomain.getKey());
        return api.genSig(sessionId, expireTime);
    }

    public TencentYunDomain getTencentYunDomain() {
        return tencentYunDomain;
    }

    /**
     * 请求腾讯云视频地址
     *
     * @param recordId
     * @return
     */
    public Map<String, Object> callTencentVideo(Long recordId) {
        TOeExamRecord tOeExamRecord = SystemConstant.getExamRecord(recordId);
        List<String> monitorRecordList = Arrays.asList(tOeExamRecord.getMonitorRecord().trim().toUpperCase().split(","));
        String[] streamIds = new String[monitorRecordList.size()];
        for (int i = 0; i < monitorRecordList.size(); i++) {
            streamIds[i] = SystemConstant.setStreamId(monitorUtil.getMonitorDomain().getPrefix(), recordId, MonitorVideoSourceEnum.convertToName(monitorRecordList.get(i)));
        }

        Map<String, Object> resultMap = null;
        boolean lockStreamIds = false;
        for (int i = 0; i < SystemConstant.MAX_TENCENT_VIDEO_STREAM_ID_COUNT; i++) {
            lockStreamIds = redisUtil.lock(SystemConstant.REDIS_LOCK_TENCENT_VIDEO_STREAM_ID_PREFIX + streamIds.toString(),
                    SystemConstant.REDIS_LOCK_TENCENT_VIDEO_STREAM_ID_TIME_OUT);
            if (lockStreamIds) {
                try {
                    resultMap = this.tencentVodSdk(this.getTencentYunDomain().getSecretId(),
                            this.getTencentYunDomain().getSecretKey(),
                            this.getTencentYunDomain().getQueryUrl(),
                            this.getTencentYunDomain().getVodAppId(),
                            streamIds);
                    break;
                } catch (Exception e) {
                    log.error("请求出错", e);
                    if (i == SystemConstant.MAX_TENCENT_VIDEO_STREAM_ID_COUNT - 1) {
                        tgErrorService.saveExamTgError(recordId, "execMqTencentVideoLogic");
                    } else {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }
                } finally {
                    if (Objects.nonNull(streamIds)) {
                        redisUtil.releaseLock(SystemConstant.REDIS_LOCK_TENCENT_VIDEO_STREAM_ID_PREFIX + streamIds.toString());
                    }
                }
            } else {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return resultMap;
    }

    /**
     * 腾讯云vodsdk
     *
     * @param secretId
     * @param secretKey
     * @param endPoint
     * @param subAppId
     * @param streamIds
     * @return
     */
    public Map<String, Object> tencentVodSdk(String secretId, String secretKey, String endPoint, Long subAppId, String... streamIds) {
        log.info("腾讯云vodsdk进来了");
        Map<String, Object> resultMap = null;
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户secretId，secretKey,此处还需注意密钥对的保密
            // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
            Credential cred = new Credential(secretId, secretKey);
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(endPoint);
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            VodClient client = new VodClient(cred, "", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            SearchMediaRequest req = new SearchMediaRequest();
            req.setSubAppId(subAppId);
            if (Objects.nonNull(streamIds) && streamIds.length > 0) {
                req.setStreamIds(streamIds);
            }

            // 返回的resp是一个SearchMediaResponse的实例，与请求对象对应
            SearchMediaResponse resp = client.SearchMedia(req);
            if (Objects.nonNull(resp)) {
                resultMap = new HashMap<>();
                // 输出json格式的字符串回包
                String result = SearchMediaResponse.toJsonString(resp);
                resultMap.put("object", resp);
                log.info("result:{}", result);
            }
        } catch (TencentCloudSDKException e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
        return resultMap;
    }

    /**
     * 解散房间
     *
     * @param secretId
     * @param secretKey
     * @param endPoint
     * @param region
     * @param appId
     * @param roomId
     * @return
     */
    public Map<String, Object> DismissRoomByStrRoomId(String secretId, String secretKey, String endPoint, String region, Long appId, String roomId) {
        log.info("腾讯云解散房间进来了");
        Map<String, Object> resultMap = null;
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户secretId，secretKey,此处还需注意密钥对的保密
            // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
            Credential cred = new Credential(secretId, secretKey);
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(endPoint);
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            TrtcClient client = new TrtcClient(cred, region, clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            DismissRoomByStrRoomIdRequest req = new DismissRoomByStrRoomIdRequest();
            req.setSdkAppId(appId);
            req.setRoomId(roomId);
            // 返回的resp是一个DismissRoomByStrRoomIdResponse的实例，与请求对象对应
            DismissRoomByStrRoomIdResponse resp = client.DismissRoomByStrRoomId(req);
            if (Objects.nonNull(resp)) {
                resultMap = new HashMap<>();
                // 输出json格式的字符串回包
                String result = DismissRoomByStrRoomIdResponse.toJsonString(resp);
                resultMap.put("object", resp);
                log.info("result:{}", result);
            }
        } catch (TencentCloudSDKException e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
        return resultMap;
    }
}