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.apache.http.conn.ConnectTimeoutException;
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 {
                Map<String, Object> artemisInfo = initArtemisConfigAndPath(baseEnterpriseVideo, baseEnterpriseVideo.getUrl());
                ArtemisConfig config = (ArtemisConfig) artemisInfo.get("config");
                Map<String, String> path = (Map<String, String>) artemisInfo.get("path");

                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);
                    video.setType(param.getString("viewProtocol"));
                }
            } catch (URISyntaxException e) {
                throw new RuntimeException("URL格式解析异常", e);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        videoUrlResult.addAll(videoList);
    }

    /**
     * 解析URL字符串为协议、主机+端口和路径部分
     *
     * @param url 完整的URL字符串
     * @return 包含 protocol, hostPort 和 urlPath 的Map
     */
    private Map<String, String> parseUri(String url) throws URISyntaxException {
        // 将url解析为https://192.168.1.1:8080/api/v1?pageNo=1&pageSize=20这种方式
        URI uri = new URI(url);
        String scheme = uri.getScheme();
        String protocol = scheme != null ? scheme + "://" : "";
        String hostPort = uri.getHost() + (uri.getPort() != -1 ? ":" + uri.getPort() : "");
        String urlPath = uri.getPath();

        Map<String, String> result = new HashMap<>();
        result.put("protocol", protocol);
        result.put("hostPort", hostPort);
        result.put("urlPath", urlPath);
        return result;
    }

    /**
     * 初始化Artemis配置和路径信息
     *
     * @param baseEnterpriseVideo 视频设备信息
     * @param apiUrl
     * @return 包含 ArtemisConfig、请求路径和协议的Map
     */
    private Map<String, Object> initArtemisConfigAndPath(BaseEnterpriseVideo baseEnterpriseVideo, String apiUrl) throws URISyntaxException {
        Map<String, String> uriInfo = parseUri(apiUrl);
        String protocol = uriInfo.get("protocol");
        String hostPort = uriInfo.get("hostPort");
        String urlPath = uriInfo.get("urlPath");

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

        Map<String, String> path = new HashMap<>();
        path.put(protocol, urlPath);

        Map<String, Object> result = new HashMap<>();
        result.put("config", config);
        result.put("path", path);
        return result;
    }

    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();
                            channelNo.setUrl(url);
                            channelNo.setType(CommonVideoEnum.getEnum(video.getProtocol()).getName());
                            result.add(channelNo);
                        } 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 {
            Map<String, Object> artemisInfo = initArtemisConfigAndPath(baseEnterpriseVideo, baseEnterpriseVideo.getTokenUrl());
            ArtemisConfig config = (ArtemisConfig) artemisInfo.get("config");
            Map<String, String> path = (Map<String, String>) artemisInfo.get("path");

            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;
                    /* dataJson返回结果样例
                    {"regionIndexCode":"cac9325d1ac74415b064a621595f6e09","capabilitySetName":"GPS事件能力,视频事件能力,IO能力,视频能力,录像能力,视频设备远程获取能力,设备维护能力,客流统计事件能力,状态能力","channelNo":"3","latitude":"34.4765399909899","channelType":"digital","cameraIndexCode":"9215c9a92f574a7da23523ef6894c5a2","recordLocation":"1","cameraTypeName":"xres.query.camera.type.qj","recordLocationName":"xres.query.device.store","channelTypeName":"xres.query.camera.digital","transTypeName":"TCP","cameraName":"迂回站上车区","longitude":"108.9768070075236","installLocation":"索12陕J00001(21)","updateTime":"2025-08-20T10:44:56.273+08:00","gbIndexCode":"61000000001310257002","cameraType":0,"transType":1,"createTime":"2025-04-07T11:16:01.258+08:00","capabilitySet":"event_gps,event_vss,io,vss,record,remote_vss,maintenance,event_pdc,status","encodeDevIndexCode":"94dddc8ed1124f8c9cd9537beb12ef72"}
                     */
                    commonVideoDto.setKey(dataJson.getString("cameraIndexCode"));
                    commonVideoDto.setLabel(dataJson.getString("cameraName"));
                    commonVideoDto.setTitle(dataJson.getString("cameraName"));
                    commonVideoDto.setParent(baseEnterpriseVideo.getUseUnitCode());
                    commonVideoDto.setUseRegistrationCode(dataJson.getString("installLocation"));
                    commonVideoDtos.add(commonVideoDto);
                });
                return commonVideoDtos;
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException("URL格式解析异常", e);
        } catch (ConnectTimeoutException e) {
            log.error("获取iSecureCenter视频对接平台超时:{}", e.getLocalizedMessage(), e);
            return commonVideoDtos;
        } catch (Exception e) {
            log.error("获取iSecureCenter视频对接平台摄像头列表失败，未知错误！", e);
            return commonVideoDtos;
        }
        return commonVideoDtos;
    }
}