package cn.iocoder.yudao.module.product.hik;

import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.product.enums.ApiConstants;
import cn.iocoder.yudao.module.product.enums.HikApiEnums;
import cn.iocoder.yudao.module.product.hik.dto.HikDeviceInfoDto;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 海康监控api请求工具类
 */
@Slf4j
@Component
public class HikHttpUtils {

    @Resource
    private HikProperties hikConfig;

    private static HikProperties staticHikConfig;

    @PostConstruct
    public void init(){
        staticHikConfig = hikConfig;
    }

    /**
     * 通过名字查询监控点的indexCode列表(设备的信息)
     * @return 设备信息列表
     */
    @SuppressWarnings("unchecked")
    public static List<String> getCameraIndexCodesByName(String name) {
        ArtemisConfig.host = staticHikConfig.getHost();
        ArtemisConfig.appKey = staticHikConfig.getAppKey();
        ArtemisConfig.appSecret = staticHikConfig.getAppSecret();
        final String previewURLsApi = staticHikConfig.getArtemisPath() + HikApiEnums.MONITOR_POINT_SEARCH_PAGE_V2.getUrl();
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put(staticHikConfig.getHttpSchema(), previewURLsApi);
            }
        };

        JSONObject jsonBody = new JSONObject();
        jsonBody.put("name", name);
        jsonBody.put("pageNo", 1);
        jsonBody.put("pageSize", 10);
        String body = jsonBody.toJSONString();
        String json = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, ContentType.JSON.getValue() , null);
        // {"code":"0","msg":"success","data":{"total":1,"pageNo":1,"pageSize":10,"list":[{"indexCode":"c3af4e8f707a4408a3a592d88643cabf","regionIndexCode":"c9de6044-f56c-4e2b-87f0-74a4e1644bc7","name":"半球3-bc9b5e98c917","parentIndexCode":"63e850763f434f7291bf12be57ca7216","longitude":"","latitude":"","cameraType":0,"installLocation":"","chanNum":1,"dacIndexCode":"--","capability":"@event_gps@event_vss@io@vss@record@ptz@remote_vss@maintenance@event_device@status@","channelType":"analog","decodeTag":"ga_h264","resourceType":"camera","createTime":"2023-11-13T13:50:32.365+08:00","updateTime":"2023-11-14T14:08:49.033+08:00","sort":414,"disOrder":414,"cameraRelateTalk":"7fa9b5c4db4140ab890beff7286112c5","transType":0,"treatyType":"gb_reg","cascadeType":0,"regionName":"测试环境","regionPath":"@root000000@c9de6044-f56c-4e2b-87f0-74a4e1644bc7@","regionPathName":"中富通集团股份有限公司/测试环境"}]}}
        List<String> indexCodes;
        try {
            CommonResult<Map<String, Object>> result = JSONUtil.toBean(json, CommonResult.class);
            Map<String, Object> data = result.getData();
            assert data != null;
            indexCodes = JSONUtil.parseArray(data.get("list")).stream().map(item -> (String) JSONUtil.parseObj(item).get("indexCode")).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("请求监控设备的indexCode失败：", e);
            return null;
        }
        return indexCodes;
    }

    /**
     * 获取海康摄像头 的在线状态
     * 在线状态，0离线，1在线
     * @return 状态
     */
    @SuppressWarnings("unchecked")
    public static List<Boolean> getCameraIsOnline(List<String> codes) {
        ArtemisConfig.host = staticHikConfig.getHost();
        ArtemisConfig.appKey = staticHikConfig.getAppKey();
        ArtemisConfig.appSecret = staticHikConfig.getAppSecret();
        final String previewURLsApi = staticHikConfig.getArtemisPath() + HikApiEnums.ONLINE_STATUS_PAGE_V1.getUrl();
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put(staticHikConfig.getHttpSchema(), previewURLsApi);
            }
        };

        JSONObject jsonBody = new JSONObject();
        List<Object> indexList = Arrays.asList(codes.toArray());
        jsonBody.put("indexCodes", new JSONArray(indexList));
        String body = jsonBody.toJSONString();
        String json = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, ContentType.JSON.getValue(), null);
        List<Boolean> online;
        try {
            CommonResult<Map<String, Object>> result = JSONUtil.toBean(json, CommonResult.class);
            Map<String, Object> data = result.getData();
            assert data != null;
            online = JSONUtil.parseArray(data.get("list")).stream().map(item -> JSONUtil.parseObj(item).get("online").equals(ApiConstants.INTEGER_BOOLEAN_TRUE)).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("请求监控设备的状态失败：", e);
            return null;
        }

        return online;
    }

    /***
     * 获取海康摄像头播放地址
     * type:
     * 取流协议（应用层协议），
     * “hik”:HIK私有协议，使用视频SDK进行播放时，传入此类型；
     * “rtsp”:RTSP协议；
     * “rtmp”:RTMP协议（RTMP协议只支持海康SDK协议、EHOME协议、ONVIF协议接入的设备；只支持H264视频编码和AAC音频编码）；
     * “hls”:HLS协议（HLS协议只支持海康SDK协议、EHOME协议、ONVIF协议接入的设备；只支持H264视频编码和AAC音频编码）；
     * “ws”:Websocket协议（一般用于H5视频播放器取流播放）。
     * 参数不填，默认为HIK协议
     * @return 预览地址
     */
    @SuppressWarnings("unchecked")
    public static String getCameraPreviewURL(String code, String type) {
        ArtemisConfig.host = staticHikConfig.getHost();
        ArtemisConfig.appKey = staticHikConfig.getAppKey();
        ArtemisConfig.appSecret = staticHikConfig.getAppSecret();
        final String previewURLsApi = staticHikConfig.getArtemisPath() + HikApiEnums.PREVIEW_URLS_V2.getUrl();
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put(staticHikConfig.getHttpSchema(), previewURLsApi);
            }
        };

        // 组装请求参数
        JSONObject jsonBody = new JSONObject();
        jsonBody.put("cameraIndexCode", code);
        jsonBody.put("streamType", 0);
        jsonBody.put("protocol", type);
        jsonBody.put("transmode", 0);
        jsonBody.put("expand", "transcode=0");
        jsonBody.put("streamform", "ps");
        String body = jsonBody.toJSONString();
        String json = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, ContentType.JSON.getValue() , null);
        // {"code":"0","msg":"success","data":{"url":"ws://192.168.42.15:559/openUrl/vu4P2bC"}}
        List<String> previewOriginUrls = staticHikConfig.getPreviewOriginUrls();
        if (!previewOriginUrls.isEmpty()) {
            for (int i = 0; i < previewOriginUrls.size(); i++) {
                json = json.replace(previewOriginUrls.get(i), staticHikConfig.getPreviewTargetUrls().get(i));
            }
        }
        String previewURL;
        try {
            CommonResult<Map<String, Object>> result = JSONUtil.toBean(json, CommonResult.class);
            Map<String, Object> data = result.getData();
            assert data != null;
            previewURL = (String) data.get("url");
        } catch (Exception e) {
            log.error("请求监控设备的预览地址失败：", e);
            return null;
        }

        return previewURL;
    }

    /**
     * 根据indexCode获得设备的详细信息
     * @param code 海康设备对应的indexCode
     * @return 详细信息
     */
    @SuppressWarnings("unchecked")
    public static HikDeviceInfoDto getHikDeviceInfo(String code) {
        ArtemisConfig.host = staticHikConfig.getHost();
        ArtemisConfig.appKey = staticHikConfig.getAppKey();
        ArtemisConfig.appSecret = staticHikConfig.getAppSecret();
        final String previewURLsApi = staticHikConfig.getArtemisPath() + HikApiEnums.DETAIL_BY_INDEX_CODE.getUrl();
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put(staticHikConfig.getHttpSchema(), previewURLsApi);
            }
        };

        JSONObject jsonBody = new JSONObject();
        jsonBody.put("cameraIndexCode", code);
        String json = ArtemisHttpUtil.doPostStringArtemis(path, jsonBody.toJSONString(), null, null, ContentType.JSON.getValue(), null);
        System.out.println(json);

        HikDeviceInfoDto hikDeviceInfo;
        try {
            CommonResult<HikDeviceInfoDto> result = JSONUtil.toBean(json, CommonResult.class);

            hikDeviceInfo = JSONUtil.toBean(JSONUtil.toJsonStr(result.getData()), HikDeviceInfoDto.class);
        } catch (Exception e) {
            log.error("请求设备详细信息失败：", e);
            return null;
        }

        return hikDeviceInfo;
    }
}
