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.core.common.enums.CommonResponseEnum;
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.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class ZLMediaKitUtils {

    @Value("${ZLMediaKit.ip}")
    private String ip;

    @Value("${ZLMediaKit.port}")
    private String port;

    @Value("${ZLMediaKit.secret}")
    private String secret;

    @Value("${ZLMediaKit.connectTimeout}")
    private Long connectTimeout;

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

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

    @Value("${ZLMediaKit.keepAliveDuration}")
    private Long keepAliveDuration;

    @Value("${ZLMediaKit.vhost}")
    private String vhost;

    @Value("${ZLMediaKit.app}")
    private String app;

    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 JSONObject sendPost(String api, Map<String, Object> param) {
        return sendPost(api, param, null);
    }

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

        // 构造form表单
        FormBody.Builder builder = new FormBody.Builder();
        builder.add("secret", secret);
        if (param != null && !param.keySet().isEmpty()) {
            for (String key : param.keySet()) {
                if (param.get(key) != null) {
                    builder.add(key, param.get(key).toString());
                }
            }
        }

        // 构造请求
        FormBody body = builder.build();
        Request request = new Request.Builder()
                .post(body)
                .url(url)
                .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("读取ZLM数据超时失败: %s, %s", url, e.getMessage()));
                }
                //判断连接异常
                if (e instanceof ConnectException) {
                    log.error(String.format("连接ZLM连接失败: %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("连接ZLM失败: %s, %s", call.request(), e.getMessage()));

                    if (e instanceof SocketTimeoutException) {
                        //读取超时超时异常
                        log.error(String.format("读取ZLM数据失败: %s, %s", call.request(), e.getMessage()));
                    }
                    if (e instanceof ConnectException) {
                        //判断连接异常，我这里是报Failed to connect to 10.7.5.144
                        log.error(String.format("连接ZLM失败: %s, %s", call.request(), e.getMessage()));
                    }
                }
            });
        }

        return responseJSON;
    }
 /*-------------------------------------------------以下为zlm的post请求列举----------------------------------------------------- */

    /**
     * /index/api/addStreamProxy
     *
     * @param stream 流ID（唯一标识）
     * @param url    源流地址（需包含协议前缀）
     * @return 请求结果（包含key等重要信息）
     */
    public JSONObject addStreamProxy(String stream, String url) {
        Map<String, Object> params = new HashMap<>();
        params.put("vhost", vhost);
        params.put("app", app);
        params.put("stream", stream);
        params.put("url", url);
        return sendPost("/addStreamProxy", params, null);
    }

    /**
     * /index/api/delStreamProxy
     *
     * @param key 代理流的唯一标识（由addStreamProxy返回）
     * @return 包含操作状态的JSON对象
     */
    public JSONObject delStreamProxy(String key) {
        Map<String, Object> params = new HashMap<>();
        params.put("key", key);
        return sendPost("/delStreamProxy", params, null);
    }

    /**
     * /index/api/close_streams
     *
     * @param stream 流 id
     * @return 包含操作状态的JSON对象
     */
    public JSONObject CloseStreamProxy(String stream) {
        Map<String, Object> params = new HashMap<>();
        params.put("stream", stream);
        params.put("vhost", vhost);
        params.put("app", app);
        params.put("force", true);
        return sendPost("/close_streams", params, null);
    }
	/**
     *
     * @param stream 流id
     * @return http访问地址
     */
    public String getPlayUrl(String stream) {
        // http://192.168.2.128:8080/index/api/webrtc?app=live&stream=33&type=play
        // 测试地址
        // return "http://192.168.2.128:8080/index/api/webrtc?app=live&stream=test&type=play";
        return String.format("http://%s:%s/index/api/webrtc?app=live&stream=%s&type=play", ip, port, stream);
    }

}
