package com.sz.admin.monitor.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sz.admin.monitor.constant.MediaConstant;
import com.sz.admin.monitor.pojo.dto.edgebox.AlgorithmTaskDTO;
import com.sz.admin.monitor.pojo.dto.edgebox.SetupChannelDTO;
import com.sz.core.common.enums.CommonResponseEnum;
import com.sz.core.common.exception.common.BusinessException;
import com.sz.core.util.JsonUtils;
import com.sz.platform.enums.AdminResponseEnum;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * ClassName: AiBoxRequestUtil
 * Package: com.sz.admin.monitor.utils
 * Description:
 */
@Component
@Slf4j
public class AiBoxRequestUtil {
    @Value("${edgeBox.connectTimeout}")
    private Long connectTimeout;

    @Value("${edgeBox.readTimeout}")
    private Long readTimeout;

    @Value("${edgeBox.maxIdleConnections}")
    private Integer maxIdleConnections;

    @Value("${edgeBox.keepAliveDuration}")
    private Long keepAliveDuration;
    private OkHttpClient client;

    // 回调操作
    public interface RequestCallback {
        void run(JSONObject response);
    }

    /**
     * 获取OkHttpClient
     *
     * @return 返回客户端
     */
    private OkHttpClient getClient() {
        if (Objects.isNull(client)) {
            // 设置构造参数
            OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
            // 设置连接超时时间
            httpClientBuilder.connectTimeout(connectTimeout, TimeUnit.SECONDS);
            // 设置读取超时时间
            httpClientBuilder.readTimeout(readTimeout, TimeUnit.SECONDS);
            // 设置连接池
            httpClientBuilder.connectionPool(new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.MINUTES));
            client = httpClientBuilder.build();
        }
        return client;
    }

    /**
     * 发送post请求
     *
     * @param api   路径
     * @param param 参数
     * @return 请求结果
     */
    public AlgMediaConfigResponse sendPost(String ip, String port, String api, Map<String, Object> param) {
        return sendPost(ip, port, api, param, null);
    }

    /**
     * 发送post请求
     *
     * @param api      路径
     * @param param    参数
     * @param callback 回调
     * @return 请求结果
     */
    public AlgMediaConfigResponse sendPost(String ip, String port, String api, Map<String, Object> param, AiBoxRequestUtil.RequestCallback callback) {
        OkHttpClient okHttpClient = getClient();
        String url = String.format(MediaConstant.HTTP_Edge_URL, ip, port, api);
        log.info("请求的url:{}", url);
        JSONObject responseJSON = new JSONObject();
        responseJSON.put("code", CommonResponseEnum.MEDIA_HTTP_FAIL.getCode());
        responseJSON.put("msg", CommonResponseEnum.MEDIA_HTTP_FAIL.getMessage());

        MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
        String jsonString = "";
        if (param != null) {
            jsonString = JSON.toJSONString(param);
        }
        log.info("请求体 JSON: {}", jsonString);

        RequestBody body = RequestBody.create(jsonString, JSON_TYPE);
        //  构造 Request
        Request request = new Request.Builder()
            .url(url)
            .post(body)
            .build();
        // 判断是否有回调
        if (callback == null) {
            try {
                Response response = okHttpClient.newCall(request).execute();
                if (response.isSuccessful()) {
                    ResponseBody responseBody = response.body();
                    if (responseBody != null) {
                        String responseStr = responseBody.string();
                        responseJSON = JSON.parseObject(responseStr);
                    } else {
                        response.close();
                        Objects.requireNonNull(response.body()).close();
                    }
                }
            } catch (IOException e) {
                log.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));
                //读取超时超时异常
                if (e instanceof SocketTimeoutException) {
                    log.error(String.format("读取edgeBox数据超时失败: %s, %s", url, e.getMessage()));
                }
                //判断连接异常
                if (e instanceof ConnectException) {
                    log.error(String.format("连接edgeBox连接失败: %s, %s", url, e.getMessage()));
                }
            }
        } else {
            // 进入队列
            okHttpClient.newCall(request).enqueue(new Callback() {
                // 监听成功
                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) {
                    if (response.isSuccessful()) {
                        try {
                            String responseStr = Objects.requireNonNull(response.body()).string();
                            callback.run(JSON.parseObject(responseStr));
                        } catch (IOException e) {
                            log.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));
                        }

                    } else {
                        response.close();
                        Objects.requireNonNull(response.body()).close();
                    }
                }

                // 监听失败
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    log.error(String.format("连接edgeBox失败: %s, %s", call.request(), e.getMessage()));

                    if (e instanceof SocketTimeoutException) {
                        //读取超时超时异常
                        log.error(String.format("读取连接edgeBox失败数据失败: %s, %s", call.request(), e.getMessage()));
                    }
                    if (e instanceof ConnectException) {
                        //判断连接异常，我这里是报Failed to connect to 10.7.5.144
                        log.error(String.format("连接连接edgeBox失败: %s, %s", call.request(), e.getMessage()));
                    }
                }
            });
        }
        AlgMediaConfigResponse response = JsonUtils.parseObject(responseJSON.toJSONString(), AlgMediaConfigResponse.class);
        if(response.getResult().getCode()!=0)
        {
            throw  new BusinessException(AdminResponseEnum.OPERATION_FAIL,null, response.getResult().getDesc());
        }
        return response;
    }

//    ###################################请求方法###########################################

    /**
     * 配置视频通道
     *
     * @param setupChannelDTO 参数对象
     * @return 返回值
     */
    public AlgMediaConfigResponse setupVideoChannel(String ip, String port, SetupChannelDTO setupChannelDTO) {
        Map<String, Object> map = new HashMap<>();
        map.put("MediaName", setupChannelDTO.getMediaName());
        map.put("MediaUrl", setupChannelDTO.getMediaUrl());
        map.put("GBTransport", false);
        map.put("RtspTransport", false);
        map.put("MediaDesc", setupChannelDTO.getMediaDesc());
        map.put("ProtocolType", 0);
        return sendPost(ip, port, "/alg_media_config", map, null);
    }

    /**
     * 查询视频通道列表
     */
    public List<AlgMediaConfigResponse.MediaStreamInfo> getVideoChannelList(String ip, String port) {
        AlgMediaConfigResponse response = sendPost(ip, port, "/alg_media_fetch", null, null);
        return response.getContent();
    }
    /**
     *  删除视频通道
     * @param mediaName  通道名称
     * @return
     */
    public AlgMediaConfigResponse deleteVideoChannel(String ip, String port, String mediaName) {
        Map<String, Object> map = new HashMap<>();
        map.put("MediaName",mediaName);
        return sendPost(ip, port, "/alg_media_delete", map, null);
    }

    /**
     * 配置任务
     */
    public AlgMediaConfigResponse setupTask(String ip, String port, AlgorithmTaskDTO algTaskConfigDto) {
        Map<String, Object> map = new HashMap<>();
        map.put("AlgTaskSession", algTaskConfigDto.getAlgTaskSession());
        map.put("MediaName", algTaskConfigDto.getMediaName());
        map.put("TaskDesc", algTaskConfigDto.getTaskDesc());
        map.put("AlgInfo",algTaskConfigDto.getAlgInfo());
        // TODO 暂时写死
        map.put("MetadataUrl", "http://192.168.2.123:9991/api/admin/algorithm-task/alarm");
        map.put("Restart", true);
        map.put("UserData", algTaskConfigDto.getUserData());
        return sendPost(ip, port, "/alg_task_config", map, null);
    }
    /**
     * 控制设备视频任务
     * @param algTaskSession   会话编号
     * @param controlCommand  0 关闭 1开启
     * @return
     */
    public AlgMediaConfigResponse controlTask(String ip, String port, String algTaskSession, int controlCommand) {
        Map<String, Object> map = new HashMap<>();
        map.put("AlgTaskSession", algTaskSession);
        map.put("ControlCommand", controlCommand);
        return sendPost(ip, port, "/alg_task_control", map, null);
    }
    /**
     *  删除设备视频任务
     */
    public AlgMediaConfigResponse deleteTask(String ip, String port, String algTaskSession) {
        Map<String, Object> map = new HashMap<>();
        map.put("AlgTaskSession",algTaskSession);
        return sendPost(ip, port, "/alg_task_delete", map, null);
    }
    /**
     *  创建人脸库
     */
    public AlgMediaConfigResponse createFaceLibrary(String ip, String port, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("albumName",name);
        return sendPost(ip, port, "/api_repository_create", map, null);
    }
    /**
     *  人脸库的删除
     */
    public AlgMediaConfigResponse deleteFaceLibrary(String ip, String port, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("albumName",name);
        return sendPost(ip, port, "/api_repository_delete", map, null);
    }
    /**
     * 注册到人脸库
     */
    public AlgMediaConfigResponse registerFaceLibrary(String ip, String port, String albumName, String faceSign, String realName, String image) {
        Map<String, Object> map = new HashMap<>();
        map.put("albumName",albumName);
        map.put("name",faceSign);
        map.put("realName",realName);
        map.put("image",image);
        return sendPost(ip, port, "/api_register_face", map, null);
    }
    /**
     * 注册到人脸库
     */
    public AlgMediaConfigResponse registerFaceLibrary(String ip, String port, String albumName, String faceSign, String realName, String image, String featureName) {
        Map<String, Object> map = new HashMap<>();
        map.put("albumName",albumName);
        map.put("name",faceSign);
        map.put("realName",realName);
        map.put("image",image);
        map.put("featureName",featureName);
        return sendPost(ip, port, "/api_register_face", map, null);
    }
    /**
     *  删除注册到人脸库的信息
     */
    public AlgMediaConfigResponse deleteFaceInfo(String ip, String port, String faceSign, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("albumName",name);
        map.put("photoName",faceSign);  // 用户标识
        return sendPost(ip, port, "/api_face_delete", map, null);
    }

}
