package com.narutohuo.xindazhou.ble.util

import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.bluetooth.BluetoothProfile
import android.content.Context
import com.narutohuo.xindazhou.ble.config.BLEConstants
import com.narutohuo.xindazhou.core.log.ILog
import java.util.UUID

/**
 * BLE连接器
 * 
 * 负责与单个 BLE 设备建立 GATT 连接并完成服务发现
 * 连接成功后会把需要写入的特征回调给业务层
 */
class BleConnector(
    private val context: Context,
    private val device: BluetoothDevice,
    private val onConnected: (BluetoothGatt, BluetoothGattCharacteristic) -> Unit,
    private val onDisconnected: () -> Unit,
    private val onError: (String) -> Unit
) {
    
    private val tag = "BleConnector"
    
    private var gatt: BluetoothGatt? = null
    private var writeChar: BluetoothGattCharacteristic? = null
    private var notifyChar: BluetoothGattCharacteristic? = null
    
    /** 供外部发送模块注入的回调对象 */
    var packetSender: BlePacketSender? = null
    
    /**
     * 发起连接
     */
    @SuppressLint("MissingPermission")
    fun connect() {
        ILog.d(tag, "========== 开始连接设备 ==========")
        ILog.d(tag, "设备地址: ${device.address}")
        ILog.d(tag, "设备名称: ${device.name ?: "未知"}")
        ILog.d(tag, "设备类型: ${device.type}")
        ILog.d(tag, "绑定状态: ${device.bondState} (10=NONE, 11=BONDING, 12=BONDED)")
        ILog.d(tag, "====================================")
        
        try {
            gatt = device.connectGatt(context, false, gattCallback)
            if (gatt != null) {
                ILog.d(tag, "✅ connectGatt() 调用成功，gatt 对象已创建")
                ILog.d(tag, "等待 onConnectionStateChange 回调...")
            } else {
                ILog.e(tag, "❌ connectGatt() 返回 null")
                onError("连接失败: connectGatt() 返回 null")
            }
        } catch (e: SecurityException) {
            ILog.e(tag, "❌ 连接权限不足", e)
            onError("连接权限不足: ${e.message}")
        } catch (e: Exception) {
            ILog.e(tag, "❌ 连接失败", e)
            onError("连接失败: ${e.message}")
        }
    }
    
    /**
     * 断开连接并释放资源
     */
    @SuppressLint("MissingPermission")
    fun disconnect() {
        try {
            gatt?.disconnect()
            gatt?.close()
            gatt = null
            writeChar = null
            notifyChar = null
            ILog.d(tag, "已断开连接")
        } catch (e: Exception) {
            ILog.e(tag, "断开连接失败", e)
        }
    }
    
    /**
     * GATT 回调
     */
    private val gattCallback = object : BluetoothGattCallback() {
        
        @SuppressLint("MissingPermission")
        override fun onConnectionStateChange(
            gatt: BluetoothGatt, status: Int, newState: Int
        ) {
            ILog.d(tag, "========== 连接状态变化 ==========")
            ILog.d(tag, "设备地址: ${device.address}")
            ILog.d(tag, "状态码: $status (0=SUCCESS)")
            ILog.d(tag, "新状态: $newState (1=DISCONNECTED, 2=CONNECTING, 3=CONNECTED)")
            ILog.d(tag, "====================================")
            
            when (newState) {
                BluetoothProfile.STATE_CONNECTED -> {
                    ILog.d(tag, "✅ 已连接设备 ${device.address}，开始发现服务")
                    try {
                        gatt.discoverServices()  // 触发 onServicesDiscovered
                        ILog.d(tag, "已调用 discoverServices()")
                    } catch (e: SecurityException) {
                        ILog.e(tag, "❌ 发现服务权限不足", e)
                        onError("发现服务权限不足: ${e.message}")
                    } catch (e: Exception) {
                        ILog.e(tag, "❌ 发现服务失败", e)
                        onError("发现服务失败: ${e.message}")
                    }
                }
                BluetoothProfile.STATE_DISCONNECTED -> {
                    ILog.d(tag, "已断开连接 (状态码: $status)")
                    onDisconnected()
                    disconnect()
                }
                BluetoothProfile.STATE_CONNECTING -> {
                    ILog.d(tag, "正在连接...")
                }
                BluetoothProfile.STATE_DISCONNECTING -> {
                    ILog.d(tag, "正在断开连接...")
                }
                else -> {
                    ILog.w(tag, "未知状态: $newState")
                }
            }
        }
        
        @SuppressLint("MissingPermission")
        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            ILog.d(tag, "========== 服务发现回调 ==========")
            ILog.d(tag, "状态码: $status (0=GATT_SUCCESS)")
            ILog.d(tag, "====================================")
            
            if (status != BluetoothGatt.GATT_SUCCESS) {
                ILog.e(tag, "❌ 发现服务失败，状态码: $status")
                onError("发现服务失败 status=$status")
                return
            }
            
            ILog.d(tag, "✅ onServicesDiscovered: 发现服务成功")
            
            // 打印所有服务
            val allServices = gatt.services
            ILog.d(tag, "服务列表 (${allServices.size} 个):")
            allServices.forEach { svc ->
                ILog.d(tag, "  服务 UUID: ${svc.uuid}")
                val characteristics = svc.characteristics
                ILog.d(tag, "    特征列表 (${characteristics.size} 个):")
                characteristics.forEach { char ->
                    ILog.d(tag, "      特征 UUID: ${char.uuid}")
                }
            }
            
            val targetServiceUuid = BLEConstants.SERVICE_UUID
            val targetWriteCharUuid = BLEConstants.WRITE_CHARACTERISTIC_UUID
            val targetNotifyCharUuid = BLEConstants.NOTIFY_CHARACTERISTIC_UUID
            val charConfigUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
            
            ILog.d(tag, "目标服务 UUID: $targetServiceUuid")
            ILog.d(tag, "目标写特征 UUID: $targetWriteCharUuid")
            ILog.d(tag, "目标通知特征 UUID: $targetNotifyCharUuid")
            
            val service = this@BleConnector.gatt!!.getService(targetServiceUuid)
            
            if (service == null) {
                val availableServices = allServices.map { it.uuid.toString() }.joinToString(", ")
                ILog.e(tag, "❌❌❌ 未找到目标服务 $targetServiceUuid")
                ILog.e(tag, "🔴🔴🔴 可用服务列表: $availableServices")
                android.util.Log.e(tag, "❌❌❌ 未找到目标服务 $targetServiceUuid")
                android.util.Log.e(tag, "🔴🔴🔴 可用服务列表: $availableServices")
                onError("未找到目标服务 $targetServiceUuid，可用服务: $availableServices")
                return
            }
            
            ILog.d(tag, "✅ 找到目标服务: ${service.uuid}")
            
            writeChar = service.getCharacteristic(targetWriteCharUuid)
            notifyChar = service.getCharacteristic(targetNotifyCharUuid)
            
            if (writeChar == null) {
                val availableChars = service.characteristics.map { it.uuid.toString() }.joinToString(", ")
                ILog.e(tag, "❌ 未找到写特征 $targetWriteCharUuid")
                ILog.e(tag, "可用特征: $availableChars")
                onError("未找到写特征 $targetWriteCharUuid，可用特征: $availableChars")
                return
            }
            
            ILog.d(tag, "✅ 找到写特征: ${writeChar!!.uuid}")
            
            if (notifyChar == null) {
                val availableChars = service.characteristics.map { it.uuid.toString() }.joinToString(", ")
                ILog.e(tag, "❌ 未找到通知特征 $targetNotifyCharUuid")
                ILog.e(tag, "可用特征: $availableChars")
                onError("未找到通知特征 $targetNotifyCharUuid，可用特征: $availableChars")
                return
            }
            
            ILog.d(tag, "✅ 找到通知特征: ${notifyChar!!.uuid}")
            
            // 启用通知
            try {
                ILog.d(tag, "开始启用通知...")
                this@BleConnector.gatt!!.setCharacteristicNotification(notifyChar, true)
                ILog.d(tag, "已调用 setCharacteristicNotification(true)")
                
                val descriptor = notifyChar?.getDescriptor(charConfigUuid)
                if (descriptor == null) {
                    ILog.e(tag, "❌ 未找到 CCCD descriptor (UUID: $charConfigUuid)")
                    onError("未找到 CCCD descriptor")
                    return
                }
                
                ILog.d(tag, "找到 CCCD descriptor，准备写入...")
                descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                this@BleConnector.gatt!!.writeDescriptor(descriptor)
                ILog.d(tag, "已调用 writeDescriptor()")
                
                ILog.d(tag, "✅ 通知设置完成，等待 CCCD 写入回调")
                ILog.d(tag, "✅ 连接流程完成，调用 onConnected 回调")
                
                // 连接成功，回调
                onConnected(this@BleConnector.gatt!!, writeChar!!)
                
            } catch (e: SecurityException) {
                ILog.e(tag, "❌ 启用通知权限不足", e)
                onError("启用通知权限不足: ${e.message}")
            } catch (e: Exception) {
                ILog.e(tag, "❌ 启用通知失败", e)
                onError("启用通知失败: ${e.message}")
            }
        }
        
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            ILog.d(tag, "onCharacteristicWrite: status=$status")
            packetSender?.onCharacteristicWrite(characteristic, status)
        }
        
        override fun onDescriptorWrite(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {
            super.onDescriptorWrite(gatt, descriptor, status)
            ILog.d(tag, "========== CCCD 写入回调 ==========")
            ILog.d(tag, "状态码: $status (0=GATT_SUCCESS)")
            ILog.d(tag, "Descriptor UUID: ${descriptor?.uuid}")
            ILog.d(tag, "====================================")
            
            if (status == BluetoothGatt.GATT_SUCCESS) {
                ILog.d(tag, "✅ CCCD 写入成功，通知已启用")
            } else {
                ILog.e(tag, "❌ CCCD 写入失败，状态码: $status")
            }
        }
        
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic
        ) {
            super.onCharacteristicChanged(gatt, characteristic)
            ILog.d(tag, "收到通知")
            packetSender?.onCharacteristicNotify(characteristic)
        }
    }
}

