import CoreBluetooth
import Foundation
import React

@objc(BluetoothStateManager)
class BluetoothStateManager: RCTEventEmitter {
    static let EVENT_STATE_CHANGED = "BluetoothStateChanged"

    private static var central: CBCentralManager?
    private static var delegateProxy: DelegateProxy?

    private var observing = false
    private var listenerCount = 0

    override init() {
        super.init()
        if Self.central == nil {
            Self.delegateProxy = DelegateProxy(owner: self)
            // main queue để đảm bảo callback/trạng thái nhất quán với UI
            Self.central = CBCentralManager(
                delegate: Self.delegateProxy!,
                queue: .main,
                options: [CBCentralManagerOptionShowPowerAlertKey: false]
            )
        } else {
            // cập nhật owner khi module được re-init
            Self.delegateProxy?.owner = self
        }
    }

    // MARK: RCTEventEmitter

    @objc override static func requiresMainQueueSetup() -> Bool { true }

    override func supportedEvents() -> [String]! { [Self.EVENT_STATE_CHANGED] }

    override func startObserving() {
        observing = true
        // gửi trạng thái hiện tại ngay khi có subscriber
        if let central = Self.central {
            sendEvent(withName: Self.EVENT_STATE_CHANGED, body: stateString(from: central.state))
        }
    }

    override func stopObserving() { observing = false }

    // (RN mới không cần export addListener/removeListener; RCTEventEmitter tự quản)
    override func addListener(_ eventName: String!) {
        super.addListener(eventName)
        listenerCount += 1
        startObserving()
    }

    override func removeListeners(_ count: Double) {
        super.removeListeners(count)
        listenerCount = max(0, listenerCount - Int(count))
        // RN sẽ gọi khi unsub hết → dừng
        if listenerCount == 0 { stopObserving() }
    }

    // MARK: Public API (Promise)

    @objc(getState:rejecter:)
    func getState(
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        guard let central = Self.central else {
            resolve("Unsupported")
            return
        }
        // Nếu còn "unknown", đợi 100ms rồi trả lại (nhẹ nhàng)
        if central.state == .unknown {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
                guard let s = self, let c = Self.central else {
                    resolve("Unsupported")
                    return
                }
                resolve(s.stateString(from: c.state))
            }
        } else {
            resolve(stateString(from: central.state))
        }
    }

    @objc(requestToEnable:rejecter:)
    func requestToEnable(
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        // iOS không cho bật Bluetooth bằng code
        reject(
            "ERROR_NOT_SUPPORTED",
            "iOS cannot programmatically enable Bluetooth. Please enable it in Settings/Control Center.",
            nil)
    }

    // MARK: Helpers

    fileprivate func emit(_ newState: CBManagerState) {
        guard observing else { return }
        sendEvent(withName: Self.EVENT_STATE_CHANGED, body: stateString(from: newState))
    }

    private func stateString(from s: CBManagerState) -> String {
        switch s {
        case .poweredOn: return "PoweredOn"
        case .poweredOff: return "PoweredOff"
        case .unauthorized: return "Unauthorized"
        case .unsupported: return "Unsupported"
        case .resetting: return "Resetting"
        case .unknown: fallthrough
        @unknown default: return "Unknown"
        }
    }

    // Delegate proxy giữ mạnh, nhưng trỏ yếu về owner để tránh retain cycle
    fileprivate class DelegateProxy: NSObject, CBCentralManagerDelegate {
        weak var owner: BluetoothStateManager?
        init(owner: BluetoothStateManager) { self.owner = owner }

        func centralManagerDidUpdateState(_ central: CBCentralManager) {
            owner?.emit(central.state)
        }
    }
}
