import Foundation
import ImageCaptureCore

/// 自动识别 USB 相机品牌并委托给对应品牌服务。
@MainActor
final class AutoDetectCameraService: NSObject, CameraServiceProtocol {
    private(set) var brand: CameraBrand = .sony
    private(set) var connectionState: CameraConnectionState = .disconnected
    var onConnectionStateChange: ((CameraConnectionState) -> Void)?
    var onNewAsset: ((CameraAsset) -> Void)?

    private var activeService: (any CameraServiceProtocol)?
    private var pendingCamera: ICCameraDevice?
    private let usbBrowser = SharedUSBCameraBrowserHub.controller
    private var isConnectingCamera = false
    private var isDisconnecting = false

    override init() {
        super.init()
        bindUSBBrowserCallbacks()
    }

    func connect() async {
        CameraTetheringLogger.log("AutoDetectCameraService.connect()")
        if let activeService {
            CameraTetheringLogger.log("AutoDetect: 已有活动服务，复用连接")
            connectionState = activeService.connectionState
            rebindActiveServiceCallbacks()
            flushPendingAssetsIfNeeded(on: activeService)
            onConnectionStateChange?(connectionState)
            return
        }

        isConnectingCamera = false
        connectionState = .searching
        onConnectionStateChange?(.searching)

        let started = await usbBrowser.start()
        guard started else {
            connectionState = .error("权限被拒绝")
            onConnectionStateChange?(.error("权限被拒绝"))
            return
        }
    }

    /// 页面离开：清空 UI 回调，保持 ICC/PTP 会话与 Browser。
    func detachFromUI() {
        CameraTetheringLogger.log("AutoDetectCameraService.detachFromUI()")
        onConnectionStateChange = nil
        onNewAsset = nil
        activeService?.detachFromUI()
    }

    func shutdown() async {
        guard !isDisconnecting else { return }
        isDisconnecting = true
        defer { isDisconnecting = false }

        CameraTetheringLogger.log("AutoDetectCameraService.shutdown()")
        isConnectingCamera = false

        if let activeService {
            await activeService.shutdown()
        }
        activeService = nil
        pendingCamera = nil

        usbBrowser.stop()
        USBCameraReconnectHint.markDisconnected()
        try? await Task.sleep(nanoseconds: 300_000_000)
        connectionState = .disconnected
        onConnectionStateChange?(.disconnected)
    }

    /// 重新搜索 USB 相机（未连接时可手动触发，或 App 回到前台时调用）。
    func restartDiscovery() async {
        CameraTetheringLogger.log("AutoDetectCameraService.restartDiscovery()")
        guard activeService == nil else {
            CameraTetheringLogger.log("AutoDetect: 已连接，跳过 restartDiscovery")
            return
        }
        isConnectingCamera = false
        connectionState = .searching
        onConnectionStateChange?(.searching)
        await usbBrowser.restart()
    }

    func listAssets() async throws -> [CameraAsset] {
        guard let activeService else {
            throw CameraServiceError.notConnected
        }
        return try await activeService.listAssets()
    }

    func downloadAsset(_ asset: CameraAsset) async throws -> URL {
        guard let activeService else {
            throw CameraServiceError.notConnected
        }
        return try await activeService.downloadAsset(asset)
    }

    private func bindUSBBrowserCallbacks() {
        usbBrowser.onCameraDiscovered = { [weak self] camera, source in
            Task { @MainActor in
                await self?.handleCameraDiscovered(camera, source: source)
            }
        }
        usbBrowser.onCameraRemoved = { [weak self] device in
            Task { @MainActor in
                await self?.handleCameraRemoved(device)
            }
        }
        usbBrowser.onAuthorizationDenied = { [weak self] in
            Task { @MainActor in
                guard let self else { return }
                self.connectionState = .error("权限被拒绝")
                self.onConnectionStateChange?(.error("权限被拒绝"))
            }
        }
        usbBrowser.onScanTimeout = { [weak self] in
            Task { @MainActor in
                guard let self, self.activeService == nil, !self.isConnectingCamera else { return }
                let message = "未发现 USB 相机。请确认：① 相机 USB 设为「照片传输/电脑遥控」② 存储卡内至少有 1 张照片 ③ 先连手机再连相机 ④ 进入页面后重新插拔 USB 线"
                self.connectionState = .error(message)
                self.onConnectionStateChange?(.error(message))
            }
        }
    }

    private func handleCameraDiscovered(_ camera: ICCameraDevice, source: String) async {
        guard activeService == nil, !isConnectingCamera, !isDisconnecting else {
            CameraTetheringLogger.log("AutoDetect: 忽略重复发现 (\(source))")
            return
        }

        let vendorID = Int(camera.usbVendorID)
        guard let detectedBrand = CameraBrand.detect(from: camera) else {
            let message = "不支持的相机品牌 (Vendor ID: 0x\(String(vendorID, radix: 16)))"
            CameraTetheringLogger.log(message)
            connectionState = .error(message)
            onConnectionStateChange?(.error(message))
            return
        }

        isConnectingCamera = true
        await activateService(for: camera, brand: detectedBrand)
        isConnectingCamera = false
    }

    private func handleCameraRemoved(_ device: ICDevice) async {
        guard !isDisconnecting else { return }
        guard activeService != nil else { return }
        guard device.uuidString == pendingCamera?.uuidString else { return }

        CameraTetheringLogger.log("AutoDetect: 相机已物理移除 \(device.name ?? "?")")
        pendingCamera = nil
        if let activeService {
            await activeService.shutdown()
        }
        activeService = nil
        usbBrowser.resetNotifiedDevices()
        connectionState = .disconnected
        onConnectionStateChange?(.disconnected)
    }

    private func activateService(for camera: ICCameraDevice, brand detectedBrand: CameraBrand) async {
        brand = detectedBrand
        let service = CameraServiceFactory.make(brand: detectedBrand)

        activeService = service
        pendingCamera = camera
        rebindActiveServiceCallbacks()

        connectionState = .connecting
        onConnectionStateChange?(.connecting)

        CameraTetheringLogger.log("AutoDetect: 挂载 \(detectedBrand.displayName) 服务 (source attach)…")
        switch detectedBrand {
        case .sony:
            if let sony = service as? SonyCameraService {
                await sony.attach(to: camera)
            }
        case .canon:
            if let canon = service as? CanonCameraService {
                await canon.attach(to: camera)
            }
        case .nikon:
            connectionState = .error("Nikon 相机尚未实现")
            onConnectionStateChange?(.error("Nikon 相机尚未实现"))
        }
    }

    private func rebindActiveServiceCallbacks() {
        guard let activeService else { return }
        activeService.onConnectionStateChange = { [weak self] state in
            Task { @MainActor in
                self?.connectionState = state
                self?.onConnectionStateChange?(state)
            }
        }
        activeService.onNewAsset = { [weak self] asset in
            self?.onNewAsset?(asset)
        }
    }

    private func flushPendingAssetsIfNeeded(on service: any CameraServiceProtocol) {
        if let sony = service as? SonyCameraService {
            sony.reattachToUI()
        } else if let canon = service as? CanonCameraService {
            canon.reattachToUI()
        }
    }
}
