package com.yeejoin.amos.boot.module.common.biz.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import com.yeejoin.amos.boot.biz.common.dto.CommonVideoDto;
import com.yeejoin.amos.boot.biz.common.enums.CommonVideoEnum;
import com.yeejoin.amos.boot.module.common.api.dto.BaseEnterpriseVideoDto;
import com.yeejoin.amos.boot.module.common.api.entity.BaseEnterpriseVideo;
import com.yeejoin.amos.boot.module.common.api.enums.VideoIntegrationPlatformEnum;
import com.yeejoin.amos.boot.module.common.api.mapper.BaseEnterpriseVideoMapper;
import com.yeejoin.amos.boot.module.common.api.service.IBaseEnterpriseVideoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.yeejoin.amos.boot.biz.common.constants.VideoConstant.CODE_200;

/**
 * 单位下摄像头表服务实现类
 *
 * @author system_generator
 * @date 2024-10-09
 */
@Service
@Slf4j
public class BaseEnterpriseVideoServiceImpl extends BaseService<BaseEnterpriseVideoDto, BaseEnterpriseVideo, BaseEnterpriseVideoMapper> implements IBaseEnterpriseVideoService {

    @Value("${cylinder.video.default.image.url:/upload/tzs/cylinder/no-connect.png}")
    private String defaultVideoUrl;

    public List<CommonVideoDto> getUnitVideoUrl(String useUnitCode, String regionCode) {
        List<CommonVideoDto> result = new ArrayList<>();
        LambdaQueryWrapper<BaseEnterpriseVideo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BaseEnterpriseVideo::getUseUnitCode, useUnitCode);
        wrapper.eq(BaseEnterpriseVideo::getIsEnabled, true);
        wrapper.like(StringUtils.isNotEmpty(regionCode), BaseEnterpriseVideo::getRegionCode, regionCode);
        List<BaseEnterpriseVideo> videos = this.getBaseMapper().selectList(wrapper);
        if (ValidationUtil.isEmpty(videos)) {
            return result;
        }
        // 将videos按对接平台字段分组，并存放Map<String, List<BaseEnterpriseVideo>>中
        Map<String, List<BaseEnterpriseVideo>> map = videos.stream().collect(Collectors.groupingBy(BaseEnterpriseVideo::getPlatform));
        map.forEach((key, value) -> {
            if (VideoIntegrationPlatformEnum.YS.getCode().equals(key)) {
                getYsVideoUrl(value, result);
            }
            if (VideoIntegrationPlatformEnum.ISECURECENTER.getCode().equals(key)) {
                getISecureCenterVideoUrl(value, result);
            }
        });
        
        return result;
    }

    private void getISecureCenterVideoUrl(List<BaseEnterpriseVideo> videos, List<CommonVideoDto> videoUrlResult) {
        List<CommonVideoDto> videoList = getISecureCenterCameras(videos);
        if (ValidationUtil.isEmpty(videoList)) {
            return;
        }
        BaseEnterpriseVideo baseEnterpriseVideo = videos.get(0);
        videoList.forEach(video -> {
            List<CommonVideoDto> commonVideoDtos = new ArrayList<>();
            try {
                String getCamerasUrl = baseEnterpriseVideo.getUrl();
                // 将getCamerasUrl解析为https://192.168.1.1:8080/api/v1?pageNo=1&pageSize=20这种方式
                // 使用URI标准库解析URL结构
                URI uri = new URI(getCamerasUrl);
                String scheme = uri.getScheme(); // 获取协议部分（https）
                String protocol = scheme + "://"; // "https://"
                String hostPort = uri.getHost() + (uri.getPort() != -1 ? ":" + uri.getPort() : ""); // "ip:port"
                String urlPath = uri.getPath();

                ArtemisConfig config = new ArtemisConfig();
                config.setAppKey(baseEnterpriseVideo.getAppKey());
                config.setAppSecret(baseEnterpriseVideo.getAppSecret());
                config.setHost(hostPort);

                Map<String, String> path = new HashMap<String, String>(2) {
                    {
                        put(protocol, urlPath);
                    }
                };
                JSONObject param = JSONObject.parseObject(baseEnterpriseVideo.getChannelNo());// post请求Form表单参数
                param.put("cameraIndexCode", video.getKey());
                String body = param.toJSONString();
                String resultStr = ArtemisHttpUtil.doPostStringArtemis(config, path, body, null, null, "application/json", null);
                if (ValidationUtil.isEmpty(resultStr)) {
                    return;
                }
                JSONObject result = JSONObject.parseObject(resultStr);
                if (!result.get("code").equals("0")) {
                    log.error("获取iSecureCenter视频对接平台摄像头预览url失败,code:{}", result.get("code"));
                }
                if (result.get("data") == null) {
                    return;
                }
                if (result.get("data") instanceof JSONObject) {
                    JSONObject dataObj = (JSONObject) result.get("data");
                    String cameraUrl = dataObj.getString("url");
                    video.setUrl(cameraUrl);
                }
            } catch (URISyntaxException e) {
                throw new RuntimeException("URL格式解析异常", e);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        videoUrlResult.addAll(videoList);
    }

    private void getYsVideoUrl(List<BaseEnterpriseVideo> videos, List<CommonVideoDto> result) {
        for (BaseEnterpriseVideo video : videos) {
            Map<String, Object> requestInfo = new HashMap<>();
            requestInfo.put("appKey", video.getAppKey());
            requestInfo.put("appSecret", video.getAppSecret());
            String channelNos = video.getChannelNo();
            List<CommonVideoDto> channelNoList = JSONObject.parseArray(channelNos, CommonVideoDto.class);
            try {
                String accessTokenData = HttpUtil.post(video.getTokenUrl(), requestInfo);
                JSONObject jsonObject = JSON.parseObject(accessTokenData);
                String msg = jsonObject.get("msg").toString();
                String code = jsonObject.get("code").toString();
                if (CODE_200.equals(code)) {
                    String data = jsonObject.get("data").toString();
                    JSONObject objTokenJson = JSON.parseObject(data);
                    String accessToken = objTokenJson.get("accessToken").toString();
                    System.out.println(accessToken);
                    for (CommonVideoDto channelNo : channelNoList) {
                        Map<String, Object> requestVideosInfo = new HashMap<>();
                        requestVideosInfo.put("accessToken", accessToken);
                        requestVideosInfo.put("deviceSerial", video.getDeviceSerial());
                        requestVideosInfo.put("channelNo", channelNo.getKey());
                        requestVideosInfo.put("protocol", video.getProtocol());
                        requestVideosInfo.put("quality", channelNo.getQuality());
                        requestVideosInfo.put("supportH265", channelNo.getSupportH265());
                        requestVideosInfo.put("expireTime", video.getExpireTime());
                        log.info("开始获取通道信息：{}", JSONObject.toJSONString(requestVideosInfo));
                        String videoData = HttpUtil.post(video.getUrl(), requestVideosInfo);
                        JSONObject videoJsonObject = JSON.parseObject(videoData);
                        String msgVideo = videoJsonObject.get("msg").toString();
                        String codeVideo = videoJsonObject.get("code").toString();
                        if (CODE_200.equals(codeVideo)) {
                            String dataS = videoJsonObject.get("data").toString();
                            JSONObject dd = JSON.parseObject(dataS);
                            String url = dd.get("url").toString();
                            CommonVideoDto commonVideoDto = new CommonVideoDto();
                            commonVideoDto.setUrl(url);
                            commonVideoDto.setKey(channelNo.getKey());
                            commonVideoDto.setType(CommonVideoEnum.getEnum(video.getProtocol()).getName());
                            commonVideoDto.setTitle(channelNo.getTitle());
                            commonVideoDto.setThumb(channelNo.getThumb());
                            commonVideoDto.setQuality(channelNo.getQuality());
                            commonVideoDto.setSupportH265(channelNo.getSupportH265());
                            result.add(commonVideoDto);
                        } else {
                            String errorMsg = "code:" + codeVideo + "msg:" + msgVideo + "appKey:" + video.getAppKey() + "appSecret:" + video.getAppSecret() + "accessToken:" + accessToken;
                            log.info("视频地址获取失败errorMsg:{}", errorMsg);
                            this.setDefaultChannelData(result, channelNo);
                        }
                    }
                } else {
                    String errorMsg = "code:" + code + "msg:" + msg + "appKey:" + video.getAppKey() + "appSecret:" + video.getAppSecret();
                    log.info("视频token获取失败errorMsg:{}", errorMsg);
                    this.setDefaultVideoIfConnectFailed(channelNoList, result);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
                this.setDefaultVideoIfConnectFailed(channelNoList, result);
            }
        }
    }

    /**
     * 通道连接不上时，返回通道的默认图片
     *
     * @param result    返回连接的总通道
     * @param channelNo 未连接的通道
     */
    private void setDefaultChannelData(List<CommonVideoDto> result, CommonVideoDto channelNo) {
        CommonVideoDto commonVideoDto = new CommonVideoDto();
        commonVideoDto.setUrl(channelNo.getThumb());
        commonVideoDto.setKey(channelNo.getKey());
        commonVideoDto.setType(CommonVideoEnum.IMG.getName());
        commonVideoDto.setTitle(channelNo.getTitle());
        commonVideoDto.setThumb(channelNo.getThumb());
        result.add(commonVideoDto);
    }

    /**
     * 连接不上时返回的气通道信息
     *
     * @param commonVideoDtos 当前气瓶单位的所有通道
     * @param result          返回的结果集合
     */
    private void setDefaultVideoIfConnectFailed(List<CommonVideoDto> commonVideoDtos, List<CommonVideoDto> result) {
        // 先情况防止数据重复
        result.clear();
        // 每个通道设备默认值
        commonVideoDtos.forEach(channelNo -> this.setDefaultChannelData(result, channelNo));
    }

    public List<CommonVideoDto> getISecureCenterCameras(List<BaseEnterpriseVideo> videoEquipList) {
        List<BaseEnterpriseVideo> iSecureCenterVideoList = videoEquipList.stream().filter(v -> VideoIntegrationPlatformEnum.ISECURECENTER.getCode().equals(v.getPlatform())).collect(Collectors.toList());
        if (!ValidationUtil.isEmpty(iSecureCenterVideoList)) {
            // 根据iSecureCenter视频对接平台，直接获取摄像头列表
            return getRegionCameras(iSecureCenterVideoList);
        }
        return null;
    }

    /**
     * iSecureCenter视频对接平台，根据区域ID（企业统一信用代码唯一对应）获取摄像头列表。
     * 现有对接一个企业只有一条数据，取第一条数据作为企业信息。
     * @param iSecureCenterVideoList 企业列表
     * @return List<CommonVideoDto>
     */
    private List<CommonVideoDto> getRegionCameras(List<BaseEnterpriseVideo> iSecureCenterVideoList) {
        List<CommonVideoDto> commonVideoDtos = new ArrayList<>();
        BaseEnterpriseVideo baseEnterpriseVideo = iSecureCenterVideoList.get(0);
        try {
            String getCamerasUrl = baseEnterpriseVideo.getTokenUrl();
            // 将getCamerasUrl解析为https://192.168.1.1:8080/api/v1?pageNo=1&pageSize=20这种方式
            // 使用URI标准库解析URL结构
            URI uri = new URI(getCamerasUrl);
            String scheme = uri.getScheme(); // 获取协议部分（https）
            String protocol = scheme + "://"; // "https://"
            String hostPort = uri.getHost() + (uri.getPort() != -1 ? ":" + uri.getPort() : ""); // "ip:port"
            String urlPath = uri.getPath();

            ArtemisConfig config = new ArtemisConfig();
            config.setAppKey(baseEnterpriseVideo.getAppKey());
            config.setAppSecret(baseEnterpriseVideo.getAppSecret());
            config.setHost(hostPort);

            Map<String, String> path = new HashMap<String, String>(2) {
                {
                    put(protocol, urlPath);
                }
            };
            Map<String, String> paramMap = new HashMap<>();// post请求Form表单参数
            paramMap.put("regionIndexCode", baseEnterpriseVideo.getDeviceSerial());
            paramMap.put("pageNo", "1");
            paramMap.put("pageSize", "100");
            String body = JSON.toJSON(paramMap).toString();
            String resultStr = ArtemisHttpUtil.doPostStringArtemis(config, path, body, null, null, "application/json", null);
            if (ValidationUtil.isEmpty(resultStr)) {
                return null;
            }
            JSONObject result = JSONObject.parseObject(resultStr);
            if (!result.get("code").equals("0")) {
                log.error("获取iSecureCenter视频对接平台摄像头列表失败,code:{}", result.get("code"));
                return commonVideoDtos;
            }
            if (result.get("data") == null) {
                return commonVideoDtos;
            }
            if (result.get("data") instanceof JSONObject) {
                JSONObject dataObj = (JSONObject) result.get("data");
                JSONArray dataList = dataObj.getJSONArray("list");
                if (ValidationUtil.isEmpty(dataList)) {
                    return commonVideoDtos;
                }
                dataList.forEach(data -> {
                    CommonVideoDto commonVideoDto = new CommonVideoDto();
                    JSONObject dataJson = (JSONObject) data;
                    commonVideoDto.setKey(dataJson.getString("cameraIndexCode"));
                    commonVideoDto.setLabel(dataJson.getString("cameraName"));
                    commonVideoDto.setTitle(dataJson.getString("cameraName"));
                    commonVideoDto.setParent(baseEnterpriseVideo.getUseUnitCode());
                    commonVideoDtos.add(commonVideoDto);
                });
                return commonVideoDtos;
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException("URL格式解析异常", e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return commonVideoDtos;
    }
}