package com.ruoyi.common.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.jiguang.sdk.api.DeviceApi;
import cn.jiguang.sdk.api.PushApi;
import cn.jiguang.sdk.bean.push.PushSendParam;
import cn.jiguang.sdk.bean.push.PushSendParam;
import cn.jiguang.sdk.bean.push.PushSendResult;
import cn.jiguang.sdk.exception.ApiErrorException;
import com.google.gson.Gson;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.*;

/**
 * 极光推送工具类 (适配 SDK 5.3.0)
 * 用于 IM 系统的离线消息推送
 */
@Component
public class JpushClientUtil {

    private static final Logger log = LoggerFactory.getLogger(JpushClientUtil.class);
    private static final Gson gson = new Gson();
    private static final String DEVICE_API_URL = "https://device.jpush.cn/v3/devices/";
    private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");

    // 静态变量，由 Spring 初始化
    private static String appKey;
    private static String masterSecret;
    private static boolean apnsProduction;
    private static PushApi pushApi;

    private static OkHttpClient httpClient;

    // 注入的属性
//    @Value("${jpush.appKey}")
//    private String injectedAppKey;
//
//    @Value("${jpush.masterSecret}")
//    private String injectedMasterSecret;
//    private final static String injectedAppKey = "e75debc0daaed0a2a888d2f3";
//    private final static String injectedMasterSecret = "e8728877c098e641cc6c51e5";
    private final static String injectedAppKey = "d5edb270e4b1cc29616e1dd5";
    private final static String injectedMasterSecret = "a49a9fd3df40747fb6e0d180";

//    private final static String customAction  = "com.test.java.sdk.";
//    private final static String targetPackage = "com.test.java.sdk";
//    private final static String targetActivity = "Activity 组件路径;";
//    private final static String extrasParam = "S.key1=value;i.key2=3;";
//    @Value("${jpush.apnsProduction:true}")
    private final static boolean injectedApnsProduction = true;


    @PostConstruct
    public void init() {
        // 将注入的值赋给静态变量
        appKey = injectedAppKey;
        masterSecret = injectedMasterSecret;
        apnsProduction = injectedApnsProduction;

        // 初始化 PushApi
        pushApi = new PushApi.Builder()
                .setAppKey(appKey)
                .setMasterSecret(masterSecret)
                .build();

        // 初始化 OkHttpClient
        httpClient = new OkHttpClient.Builder()
                .connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
                .readTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
                .writeTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
                .build();

        log.info("极光推送工具类初始化完成");
    }

// ==================== 别名绑定方法 ====================

    /**
     * 服务端直接绑定别名，将 registrationId 与 alias 关联。
     * 调用时机：用户登录成功后，客户端上报 registrationId 即可调用。
     *
     * @param registrationId 客户端上报的设备唯一标识
     * @param alias          别名，如用户ID或手机号
     */
    public static void bindAlias(String registrationId, String alias) {
        if (registrationId == null || registrationId.isEmpty() || alias == null || alias.isEmpty()) {
            log.warn("绑定别名失败: registrationId 或 alias 为空");
            return;
        }

        // 构建请求体
        Map<String, String> bodyMap = new HashMap<>();
        bodyMap.put("alias", alias);
        String jsonBody = gson.toJson(bodyMap);

        // Basic 认证
        String auth = Base64.getEncoder().encodeToString((appKey + ":" + masterSecret).getBytes());

        RequestBody requestBody = RequestBody.create(JSON_MEDIA_TYPE,jsonBody);
        Request request = new Request.Builder()
                .url(DEVICE_API_URL + registrationId)
                .addHeader("Authorization", "Basic " + auth)
                .post(requestBody)
                .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (response.isSuccessful()) {
                log.info("别名绑定成功 | registrationId: {}, alias: {}", registrationId, alias);
            } else {
                // 极光 API 有时返回 404 但仍视为成功
                String respBody = response.body() != null ? response.body().string() : "";
                log.warn("别名绑定响应非成功，可能已成功 | registrationId: {}, alias: {}, code: {}, body: {}",
                        registrationId, alias, response.code(), respBody);
            }
        } catch (IOException e) {
            log.error("别名绑定请求异常 | registrationId: {}, alias: {}, error: {}",
                    registrationId, alias, e.getMessage(), e);
        }
    }


    // ==================== 单聊推送：按别名 ====================


    /**
     * 推送到单个用户 (别名，即 userId)
     * @param alias     用户别名
     * @param title     通知标题
     * @param content   通知内容
     * @param extras    额外参数 (如会话类型、消息类型等)
     */
    public static  void pushToUser(String alias, String title, String content, Map<String, String> extras) {
        PushSendParam param = buildPushParamWithAlias(alias, title, content, extras);
        sendPush(param, "user", alias);
    }

    // ==================== 群聊推送：按别名批量 ====================

    /**
     * 推送到多个用户 (别名批量，适合群聊离线推送)
     * @param aliases   用户别名集合
     * @param title     通知标题
     * @param content   通知内容
     * @param extras    额外参数
     */
    public static  void pushToUsers(List<String> aliases, String title, String content, Map<String, String> extras) {
        if (aliases == null || aliases.isEmpty()) return;
        PushSendParam param = buildPushParamWithAliases(aliases, title, content, extras);
        sendPush(param, "group-users", aliases.size() + " users");
    }

    // ==================== 全量推送 (谨慎使用) ====================

    /**
     * 推送给所有设备
     */
    public static  void pushToAll(String title, String content, Map<String, String> extras) {
        PushSendParam param = buildPushParamWithAll(title, content, extras);
        sendPush(param, "all", null);
    }

    // ==================== 根据 Registration ID 推送 (备用) ====================

    /**
     * 按 Registration ID 推送 (适用于未绑定别名的场景)
     */
    public static  void pushByRegistrationId(List<String> regId, String title, String content, Map<String, String> extras) {
        PushSendParam param = buildPushParamWithRegistrationId(regId, title, content, extras);
        sendPush(param, "regId", regId.size()+ " users");
    }

    // ==================== 内部构建方法 (核心适配) ====================

    /**
     * 构建单个别名的推送参数
     */
    private static    PushSendParam buildPushParamWithAlias(String alias, String title, String content, Map<String, String> extras) {
        Map<String, Object> pushBody = buildCommonPushBody(title, content, extras);
        Map map= new HashMap<>();
        map.put("alias", Arrays.asList(alias));
        pushBody.put("audience", map);
        PushSendParam param = BeanUtil.toBean(pushBody, PushSendParam.class);
        return param;
    }

    /**
     * 构建多个别名的推送参数
     */
    private static  PushSendParam buildPushParamWithAliases(List<String> aliases, String title, String content, Map<String, String> extras) {
        Map<String, Object> pushBody = buildCommonPushBody(title, content, extras);
        Map map= new HashMap<>();
        map.put("alias", aliases);
        pushBody.put("audience", map);
        return BeanUtil.toBean(pushBody, PushSendParam.class);
    }

    /**
     * 构建全量推送的参数
     */
    private static  PushSendParam buildPushParamWithAll(String title, String content, Map<String, String> extras) {
        Map<String, Object> pushBody = buildCommonPushBody(title, content, extras);
        pushBody.put("audience", "all");
        return BeanUtil.toBean(pushBody, PushSendParam.class);
    }

    /**
     * 构建 Registration ID 推送的参数
     */
    private static  PushSendParam buildPushParamWithRegistrationId(List<String> regId, String title, String content, Map<String, String> extras) {
        Map<String, Object> pushBody = buildCommonPushBody(title, content, extras);
        Map map= new HashMap<>();
        map.put("registration_id", regId);
        pushBody.put("audience", map);
        return BeanUtil.toBean(pushBody, PushSendParam.class);
    }


    /**
     * 构建通用的推送 body (包含通知和公共参数)
     */
    private static  Map<String, Object> buildCommonPushBody(String title, String content, Map<String, String> extras) {
        Map<String, Object> pushBody = new HashMap<>();
        pushBody.put("platform", "all"); // 全平台

        // 构建通知体
        Map<String, Object> notification = new HashMap<>();
        notification.put("alert", content);

        // Android 通知
        Map<String, Object> android = new HashMap<>();
        android.put("alert", content);
        android.put("title", title);
//        //点击消息跳转至
//        Map<String, String> intent= new HashMap<>();
//        String intentUrl = String.format(
//                "intent:#Intent;action=%s;component=%s/%s;S.userId=%s;end",
//                customAction, targetPackage, targetActivity, extrasParam
//        );
//        intent.put("url",intentUrl);
//        android.put("intent",intent);
        if (extras != null) {
            android.put("extras", extras);
        }
        notification.put("android", android);

        // iOS 通知
        Map<String, Object> ios = new HashMap<>();
        ios.put("alert", title);
        ios.put("sound", "default");
        ios.put("badge", "+1");
        if (extras != null) {
            ios.put("extras", extras);
        }
        notification.put("ios", ios);

        pushBody.put("notification", notification);

        // 选项
        Map<String, Object> options = new HashMap<>();
        options.put("time_to_live", 86400);
        options.put("apns_production", apnsProduction);
        pushBody.put("options", options);

        return pushBody;
    }

    /**
     * 统一发送和异常处理
     */
    private static  void sendPush(PushSendParam param, String type, String target) {
        try {
            // 调用 PushApi 的 send 方法进行推送
            PushSendResult result = pushApi.send(param);
            log.info("极光推送成功 | type: {} | target: {} | msgId: {}", type, target, result.getMessageId());
        } catch (ApiErrorException e) {
            // 处理 API 错误，可获取错误码、HTTP状态码和限流信息
            int httpStatus = e.getStats();
            int errorCode = e.getApiError().getError().getCode();
            String errorMessage = e.getApiError().getError().getMessage();
            log.error("极光推送失败 | type: {} | target: {} | httpStatus: {} | errorCode: {} | error: {}",
                    type, target, httpStatus, errorCode, errorMessage, e);
            // 此处可接入重试机制或报警
        }
    }


}
