package com.narutohuo.xindazhou.push.factory

import android.content.Context
import com.alibaba.android.arouter.launcher.ARouter
import com.narutohuo.xindazhou.core.log.ILog
import com.narutohuo.xindazhou.push.api.PushService
import com.narutohuo.xindazhou.push.impl.PushServiceImpl
import com.narutohuo.xindazhou.push.model.PushConfig
import com.narutohuo.xindazhou.push.model.PushMessage

/**
 * 推送服务工厂类
 * 
 * 提供统一的获取推送服务实例和初始化的方式
 * 推送服务是全局单例，多个界面共享同一个推送服务实例
 * 
 * 内部使用 ARouter 获取服务，实现 base-core 与 push 模块的解耦
 * 
 * **完全封装，外部调用极简**：
 * ```kotlin
 * // Application.onCreate() 中只需一行代码
 * PushServiceFactory.init(context = this) { message ->
 *     // 处理接收到的推送消息（可选）
 *     ILog.d("PushService", "收到推送: ${message.title} - ${message.content}")
 * }
 * 
 * // 后续使用（如果需要）
 * val pushService = PushServiceFactory.getInstance()
 * pushService.setAlias("user123")  // 设置别名（可选）
 * ```
 * 
 * **说明**：
 * - ✅ **完全封装**：初始化、注册推送、设置监听器都在 `init()` 中自动完成
 * - ✅ **极简调用**：只需一行代码即可完成所有初始化
 * - ✅ **可选监听器**：可以传入消息监听器，也可以不传（使用默认处理）
 */
object PushServiceFactory {
    
    /**
     * 初始化推送服务（使用默认配置，完全封装）
     * 
     * **自动完成**：
     * 1. 从资源文件读取配置
     * 2. 初始化极光推送 SDK
     * 3. 设置消息监听器（如果提供）
     * 4. 自动注册推送（开启推送）
     * 
     * 从资源文件（strings.xml）读取配置，需要在 strings.xml 中定义：
     * - push_jpush_app_key（必填）
     * - push_jpush_channel（可选，默认为 "developer-default"）
     * 
     * **在 Application.onCreate() 中调用，统一初始化推送服务**
     * - ✅ **容错处理**：初始化失败不会影响应用启动，只记录日志
     * - ✅ **同步初始化**：在主线程同步初始化，通常很快不会阻塞
     * - ✅ **只需要调用一次**，后续通过 getInstance() 获取服务实例即可
     * 
     * @param context Application 上下文
     * @param messageListener 消息监听器（可选），如果不传，使用默认处理（仅记录日志）
     * @param notificationClickListener 通知点击监听器（可选），用于处理用户点击通知栏通知的事件
     *                                  可以通过 PushMessage.extras 获取跳转参数，例如：
     *                                  - "page": 跳转页面名称（如 "detail", "home" 等）
     *                                  - "id": 业务ID（如订单ID、商品ID等）
     * @param pageMappings 页面映射规则（可选），用于自动跳转
     *                     如果设置了，当推送的 extras["page"] 匹配时，会自动跳转到对应 Activity
     *                     例如：mapOf("detail" to DetailActivity::class.java, "home" to MainActivity::class.java)
     */
    @JvmStatic
    fun init(
        context: Context,
        messageListener: ((PushMessage) -> Unit)? = null,
        notificationClickListener: ((PushMessage) -> Unit)? = null,
        pageMappings: Map<String, Class<*>>? = null
    ) {
        try {
            val config = PushConfig.fromResources(context)
            val service = PushServiceImpl.getInstance()
            
            // 1. 初始化推送服务（内部已处理异常，不会抛出）
            service.initialize(context, config)
            
            // 2. 设置消息监听器（如果提供）
            if (messageListener != null) {
                service.setMessageListener(messageListener)
            } else {
                // 默认监听器：仅记录日志
                service.setMessageListener { message ->
                    ILog.d("PushService", "收到推送消息: ${message.title} - ${message.content}")
                }
            }
            
            // 3. 设置通知点击监听器
            service.setNotificationClickListener(notificationClickListener)
            
            // 4. 自动注册推送（开启推送）
            service.register()
            
            ILog.d("PushServiceFactory", "推送服务初始化完成")
        } catch (e: Exception) {
            // 双重保险：即使内部没有抛出异常，这里也捕获一下
            // 确保初始化失败不会影响应用启动
            ILog.e("PushServiceFactory", "推送服务初始化失败，推送功能将不可用", e)
        }
    }
    
    /**
     * 初始化推送服务（使用自定义配置，完全封装）
     * 
     * **自动完成**：
     * 1. 合并配置（优先使用传入配置，缺失参数从资源文件读取）
     * 2. 初始化极光推送 SDK
     * 3. 设置消息监听器（如果提供）
     * 4. 自动注册推送（开启推送）
     * 
     * **在 Application.onCreate() 中调用，统一初始化推送服务**
     * - ✅ **容错处理**：初始化失败不会影响应用启动，只记录日志
     * - ✅ **同步初始化**：在主线程同步初始化，通常很快不会阻塞
     * - ✅ **只需要调用一次**，后续通过 getInstance() 获取服务实例即可
     * 
     * @param context Application 上下文
     * @param config 推送服务配置（可选参数会从资源文件读取默认值）
     * @param messageListener 消息监听器（可选），如果不传，使用默认处理（仅记录日志）
     * @param notificationClickListener 通知点击监听器（可选），用于处理用户点击通知栏通知的事件
     *                                  可以通过 PushMessage.extras 获取跳转参数，例如：
     *                                  - "page": 跳转页面名称（如 "detail", "home" 等）
     *                                  - "id": 业务ID（如订单ID、商品ID等）
     * @param pageMappings 页面映射规则（可选），用于自动跳转
     *                     如果设置了，当推送的 extras["page"] 匹配时，会自动跳转到对应 Activity
     *                     例如：mapOf("detail" to DetailActivity::class.java, "home" to MainActivity::class.java)
     */
    @JvmStatic
    fun init(
        context: Context,
        config: PushConfig,
        messageListener: ((PushMessage) -> Unit)? = null,
        notificationClickListener: ((PushMessage) -> Unit)? = null,
        pageMappings: Map<String, Class<*>>? = null
    ) {
        try {
            // 合并配置：优先使用传入的 config，缺失的参数从资源文件读取
            val defaultConfig = PushConfig.fromResources(context)
            val mergedConfig = PushConfig(
                appKey = config.appKey.ifEmpty { defaultConfig.appKey },
                channel = if (config.channel == "developer-default") {
                    defaultConfig.channel
                } else {
                    config.channel
                },
                debugMode = config.debugMode || defaultConfig.debugMode
            )
            
            val service = PushServiceImpl.getInstance()
            
            // 1. 初始化推送服务（内部已处理异常，不会抛出）
            service.initialize(context, mergedConfig)
            
            // 2. 设置消息监听器（如果提供）
            if (messageListener != null) {
                service.setMessageListener(messageListener)
            } else {
                // 默认监听器：仅记录日志
                service.setMessageListener { message ->
                    ILog.d("PushService", "收到推送消息: ${message.title} - ${message.content}")
                }
            }
            
            // 3. 设置通知点击监听器
            service.setNotificationClickListener(notificationClickListener)
            
            // 4. 设置页面映射规则（用于自动跳转）
            if (pageMappings != null) {
                service.setPageMappings(pageMappings)
            }
            
            // 5. 自动注册推送（开启推送）
            service.register()
            
            ILog.d("PushServiceFactory", "推送服务初始化完成")
        } catch (e: Exception) {
            // 双重保险：即使内部没有抛出异常，这里也捕获一下
            // 确保初始化失败不会影响应用启动
            ILog.e("PushServiceFactory", "推送服务初始化失败，推送功能将不可用", e)
        }
    }
    
    /**
     * 获取推送服务实例（单例）
     * 
     * 优先通过 ARouter 获取服务，如果获取不到，则回退到直接实例化
     * 注意：使用前需要先调用 init() 进行初始化
     * 
     * @return PushService实例（单例）
     */
    @JvmStatic
    fun getInstance(): PushService {
        // 优先通过 ARouter 获取服务（实现解耦）
        try {
            val arouterService = ARouter.getInstance().build("/push/service").navigation() as? PushService
            if (arouterService != null) {
                ILog.d("PushServiceFactory", "通过 ARouter 获取推送服务")
                return arouterService
            }
        } catch (e: Exception) {
            // ARouter 可能还未完全初始化，捕获异常并回退
            ILog.w("PushServiceFactory", "ARouter 获取服务失败，回退到直接实例化: ${e.message}")
        }
        
        // 回退到直接实例化（向后兼容）
        ILog.d("PushServiceFactory", "使用直接实例化")
        return PushServiceImpl.getInstance()
    }
}
