package com.fujica.abk.utils;

import com.fujica.abk.api.cache;
import com.fujica.abk.common.EventBus;
import ohos.app.Context;
import ohos.utils.zson.ZSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * HTTP请求工具类
 * HarmonyOS Java API7 版本
 */
public class api {
    // 后端gateway连接
    // private static String host = "http://192.168.12.139:10004/mobile";   //中台服务
    // private static String host = "http://192.168.12.139:10001/transfer/mobile";  //本机网关
//    private static String host = "http://192.168.12.139:10004/mobile";  // 本机中转

    private static String host = "https://gatewayservicev2dev.fujica.com.cn/transfer/mobile"; //UAT环境
    // private static String host = "https://gatewayservicev2test.fujica.com.cn/transfer/mobile"; //PRE环境

    // 前端nginx连接
//     private static String host = "https://fsabk.fujica.com.cn/api"; //正式环境
    // private static String host = "https://pre-fsh5.fujica.com.cn"; //测试环境

    /**
     * 合并URL
     */
    private static String mergeUrl(String url, String method, Object data) {
        if ("GET".equals(method) && data != null && data instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> params = (Map<String, Object>) data;
            StringBuilder paramStr = new StringBuilder();
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (paramStr.length() > 0) {
                    paramStr.append("&");
                }
                try {
                    paramStr.append(entry.getKey())
                            .append("=")
                            .append(URLEncoder.encode(String.valueOf(entry.getValue()), "UTF-8"));
                } catch (Exception e) {
                    paramStr.append(entry.getKey())
                            .append("=")
                            .append(entry.getValue());
                }
            }
            if (paramStr.length() > 0) {
                url = url.indexOf("?") > 0 ? url + "&" + paramStr : url + "?" + paramStr;
            }
        }
        return url.startsWith("http") ? url : host + url;
    }

    /**
     * 延迟方法
     */
    public static CompletableFuture<Void> sleep() {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
    }

    /**
     * 将对象转换为JSON字符串
     */
    private static String objectToJson(Object data) {
        if (data instanceof String) {
            return (String) data;
        } else if (data instanceof Map) {
            ZSONObject jsonObj = new ZSONObject((Map<String, Object>) data);
            return ZSONObject.toZSONString(jsonObj);
        } else {
            // 对于其他对象，尝试使用反射或直接toString
            // 这里简化处理，实际项目中可能需要更复杂的序列化
            return data != null ? data.toString() : "{}";
        }
    }

    /**
     * 从JSON字符串解析为R对象
     */
    @SuppressWarnings("unchecked")
    private static <T> R<T> parseResponse(String jsonStr) {
        try {
            ZSONObject jsonObj = ZSONObject.stringToZSON(jsonStr);
            R<T> result = new R<>();
            if (jsonObj.containsKey("success")) {
                result.setSuccess(jsonObj.getBooleanValue("success"));
            }
            if (jsonObj.containsKey("msg")) {
                result.setMsg(jsonObj.getString("msg"));
            }
            if (jsonObj.containsKey("code")) {
                result.setCode(jsonObj.getIntValue("code"));
            }
            if (jsonObj.containsKey("data")) {
                // data字段可能是任意类型，这里直接设置为Object
                // 如果需要特定类型，调用方需要自己转换
                result.setData((T) jsonObj.get("data"));
            }

            return result;
        } catch (Exception e) {
            Log.error("JSON解析失败: " + e.getMessage());
            return new R<>("JSON解析失败: " + e.getMessage());
        }
    }

    /**
     * HTTP请求核心方法
     */
    public static <T> CompletableFuture<R<T>> http(Context context, String url, String method,
                                                   Object data, Boolean failToast, Boolean hideLoading) {
        Log.error("请求：" + url);
        if (failToast == null) {
            failToast = true;
        }

        // 显示Loading：默认显示，只有当hideLoading!=null && hideLoading==false时才不显示
        final boolean shouldShowLoading = !(hideLoading != null && hideLoading);
        if (shouldShowLoading) {
//            LoadingDialog.show(context);
        }

        url = mergeUrl(url, method, data);
        String token = cache.getToken(context);
        final String _url = url;
        final Boolean _failToast = failToast;
        return CompletableFuture.supplyAsync(() -> {
            HttpURLConnection connection = null;
            try {
                URL requestUrl = new URL(_url);
                connection = (HttpURLConnection) requestUrl.openConnection();

                // 设置请求方法
                connection.setRequestMethod(method);

                // 设置请求头
                connection.setRequestProperty("Accept", "application/json");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("token", token);

                // 设置超时
                connection.setConnectTimeout(10000);
                connection.setReadTimeout(60000);

                // 设置请求体（非GET请求）
                if (!"GET".equals(method) && data != null) {
                    connection.setDoOutput(true);
                    String jsonData = objectToJson(data);
                    OutputStream os = connection.getOutputStream();
                    os.write(jsonData.getBytes("UTF-8"));
                    os.flush();
                    os.close();
                }

                // 执行请求
                int responseCode = connection.getResponseCode();

                try {
                    R<T> result;
                    if (responseCode == 401) {
                        Toast.error(context, "登录过期，请重试");
                        cache.logout(context);
                        EventBus.getInstance().emit("onAuthChanged");
                        result = new R<>("登录过期，请重试");
                    } else if (responseCode != 200) {
                        String msg = "操作失败:" + responseCode;
                        Toast.error(context, msg);
                        Log.info("响应:" + responseCode);
                        result = new R<>(msg);
                    } else {
                        // 读取响应
                        InputStream inputStream = connection.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        reader.close();
                        inputStream.close();

                        String resultStr = response.toString();
                        Log.error("响应：" + resultStr);
                        result = parseResponse(resultStr);

                        if (result != null && !result.isSuccess() && _failToast) {
                            String errorMsg = result.getMsg() != null ? result.getMsg() : "操作失败" + result.getCode();
                            Toast.error(context, errorMsg);
                        }
                        Log.info("响应:" + resultStr);
                        if (result == null) {
                            result = new R<>("解析响应失败");
                        }
                    }

                    return result;
                } catch (Exception e) {
                    String msg = "操作失败" + e.getMessage();
                    Toast.error(context, msg);
                    Log.error("响应解析错误: " + e.getMessage());

                    return new R<>(msg);
                }
            } catch (IOException e) {
                String msg = (e.getMessage() != null && (e.getMessage().contains("2300006") || e.getMessage().contains("2300007")))
                        ? "网络连接失败" : e.getMessage() + ":" + e.getClass().getSimpleName();
                Toast.error(context, msg);
                Log.error("请求错误: " + e.getMessage());

                return new R<>(msg);
            } catch (Exception e) {
                String msg = "操作失败" + e.getMessage();
                Toast.error(context, msg);
                Log.error("请求异常: " + e.getMessage());

                return new R<>(msg);
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                if (shouldShowLoading) {
//                    LoadingDialog.hide();
                }
            }
        });
    }

    /**
     * DELETE请求
     */
    public static <T> CompletableFuture<R<T>> del(Context context, String url, Object data) {
        return http(context, url, "DELETE", data, null, null);
    }

    /**
     * POST请求
     */
    public static <T> CompletableFuture<R<T>> post(Context context, String url, Object data) {
        return http(context, url, "POST", data, null, null);
    }

    /**
     * POST请求（带选项）
     */
    public static <T> CompletableFuture<R<T>> post1(Context context, ApiOption option) {
        return http(context, option.getUrl(), "POST", option.getData(), option.getToast(), option.getHideLoading());
    }

    /**
     * GET请求（带选项）
     */
    public static <T> CompletableFuture<R<T>> get1(Context context, ApiOption option) {
        return http(context, option.getUrl(), "GET", option.getData(), option.getToast(), option.getHideLoading());
    }


    /**
     * PUT请求（带选项）
     */
    public static <T> CompletableFuture<R<T>> put1(Context context, ApiOption option) {
        return http(context, option.getUrl(), "PUT", option.getData(), option.getToast(), option.getHideLoading());
    }

    /**
     * 文件上传
     */
    public static <T> CompletableFuture<R<T>> upload(Context context, String url, String imageUri) {
        url = url.startsWith("http") ? url : host + url;
        Log.info("请求" + url);
        String token = cache.getToken(context);

        // 显示Loading（上传默认显示loading）
//        LoadingDialog.show(context);

        String finalUrl = url;
        return CompletableFuture.supplyAsync(() -> {
            HttpURLConnection connection = null;
            try {
                URL requestUrl = new URL(finalUrl);
                connection = (HttpURLConnection) requestUrl.openConnection();

                // 设置请求方法
                connection.setRequestMethod("POST");

                // 设置请求头
                String boundary = "----WebKitFormBoundary" + System.currentTimeMillis();
                connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
                connection.setRequestProperty("Connection", "keep-alive");
                connection.setRequestProperty("token", token);
                connection.setDoOutput(true);

                // 构建multipart/form-data请求体
                OutputStream os = connection.getOutputStream();
                java.io.File file = new java.io.File(imageUri);
                if (file.exists()) {
                    // 写入文件部分
                    os.write(("--" + boundary + "\r\n").getBytes("UTF-8"));
                    os.write(("Content-Disposition: form-data; name=\"file\"; filename=\"file.jpg\"\r\n").getBytes("UTF-8"));
                    os.write(("Content-Type: image/jpg\r\n\r\n").getBytes("UTF-8"));

                    // 读取并写入文件内容
                    java.io.FileInputStream fis = new java.io.FileInputStream(file);
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = fis.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                    fis.close();

                    // 结束multipart
                    os.write(("\r\n--" + boundary + "--\r\n").getBytes("UTF-8"));
                }
                os.flush();
                os.close();

                // 执行请求
                int responseCode = connection.getResponseCode();

                try {
                    R<T> result;
                    if (responseCode != 200) {
                        String msg = "操作失败:" + responseCode;
                        Toast.error(context, msg);
                        result = new R<>(msg);
                    } else {
                        // 读取响应
                        InputStream inputStream = connection.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        reader.close();
                        inputStream.close();

                        String resultStr = response.toString();
                        result = parseResponse(resultStr);

                        if (result != null && !result.isSuccess()) {
                            String errorMsg = result.getMsg() != null ? result.getMsg() : "操作失败" + result.getCode();
                            Toast.error(context, errorMsg);
                        }
                        if (result == null) {
                            result = new R<>("解析响应失败");
                        }
                    }

                    // 隐藏Loading

                    return result;
                } catch (Exception e) {
                    String msg = "操作失败" + e.getMessage();
                    Toast.error(context, msg);
                    Log.error("响应解析错误: " + e.getMessage());

                    // 隐藏Loading

                    return new R<>(msg);
                }
            } catch (IOException e) {
                String msg = e.getMessage() + ":" + e.getClass().getSimpleName();
                Toast.error(context, msg);
                Log.error("上传错误: " + e.getMessage());

                // 隐藏Loading

                return new R<>(msg);
            } catch (Exception e) {
                String msg = "操作失败" + e.getMessage();
                Toast.error(context, msg);
                Log.error("上传异常: " + e.getMessage());

                // 隐藏Loading

                return new R<>(msg);
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
        });
    }
}
