import SwiftUI
import AVFoundation
import AudioToolbox
import Combine

// MARK: - 扫描器视图模型
class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjectsDelegate {
    @Published var detectedCodes: [DetectedCode] = []
    @Published var showAlert = false
    @Published var cameraAuthorizationStatus: AVAuthorizationStatus = .notDetermined
    @Published var isTorchOn = false
    
    var captureSession: AVCaptureSession!
    private var metadataOutput: AVCaptureMetadataOutput?
    private var videoDevice: AVCaptureDevice?
    private var isProcessingDetection = false  // 添加处理状态标记
    
    override init() {
        super.init()
        checkCameraPermission()
    }
    
    // MARK: - 相机权限管理
    
    private func checkCameraPermission() {
        logInfo("🔍 检查相机权限状态", className: "ScannerViewModel")
        
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            logInfo("✅ 相机权限已授权，立即设置捕获会话", className: "ScannerViewModel")
            cameraAuthorizationStatus = .authorized
            setupCaptureSession()
            // setupCaptureSession 现在会自动启动扫描
            
        case .notDetermined:
            logInfo("❓ 相机权限未确定，请求权限", className: "ScannerViewModel")
            requestCameraPermission()
            
        case .denied, .restricted:
            logWarning("❌ 相机权限被拒绝或受限", className: "ScannerViewModel")
            cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
            
        @unknown default:
            logWarning("❓ 未知的相机权限状态", className: "ScannerViewModel")
            cameraAuthorizationStatus = .notDetermined
        }
    }
    
    private func requestCameraPermission() {
        logInfo("🔐 请求相机权限", className: "ScannerViewModel")
        
        AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
            DispatchQueue.main.async {
                if granted {
                    logInfo("✅ 相机权限请求成功，立即设置捕获会话", className: "ScannerViewModel")
                    self?.cameraAuthorizationStatus = .authorized
                    self?.setupCaptureSession()
                    // setupCaptureSession 现在会自动启动扫描
                } else {
                    logWarning("❌ 相机权限请求被拒绝", className: "ScannerViewModel")
                    self?.cameraAuthorizationStatus = .denied
                }
            }
        }
    }
    
    func openSettings() {
        logInfo("⚙️ 打开系统设置", className: "ScannerViewModel")
        
        if let settingsUrl = URL(string: UIApplication.openSettingsURLString) {
            UIApplication.shared.open(settingsUrl) { success in
                if success {
                    logInfo("✅ 成功打开系统设置", className: "ScannerViewModel")
                } else {
                    logWarning("⚠️ 打开系统设置失败", className: "ScannerViewModel")
                }
            }
        }
    }
    
    func refreshCameraPermission() {
        logInfo("🔍 重新检查相机权限状态", className: "ScannerViewModel")
        
        // 先停止当前扫描
        if captureSession?.isRunning == true {
            stopScanning()
        }
        
        // 重新检查权限
        checkCameraPermission()
    }
    
    // MARK: - 相机设置
    
    private func setupCaptureSession() {
        logInfo("🔧 开始设置捕获会话", className: "ScannerViewModel")
        
        captureSession = AVCaptureSession()
        
        guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {
            logError("❌ 无法获取视频设备", className: "ScannerViewModel")
            showAlert = true
            return
        }
        
        // 保存视频设备引用，用于手电筒控制
        videoDevice = videoCaptureDevice
        
        let videoInput: AVCaptureDeviceInput
        
        do {
            videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
        } catch {
            logError("❌ 创建视频输入失败: \(error.localizedDescription)", className: "ScannerViewModel")
            showAlert = true
            return
        }
        
        if captureSession.canAddInput(videoInput) {
            captureSession.addInput(videoInput)
            logInfo("✅ 成功添加视频输入", className: "ScannerViewModel")
        } else {
            logError("❌ 无法添加视频输入", className: "ScannerViewModel")
            showAlert = true
            return
        }
        
        metadataOutput = AVCaptureMetadataOutput()
        
        if let metadataOutput = metadataOutput,
           captureSession.canAddOutput(metadataOutput) {
            captureSession.addOutput(metadataOutput)
            metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            metadataOutput.metadataObjectTypes = [.qr, .ean8, .ean13, .code128, .code39, .upce, .pdf417, .aztec]
            logInfo("✅ 成功添加元数据输出", className: "ScannerViewModel")
        } else {
            logError("❌ 无法添加元数据输出", className: "ScannerViewModel")
            showAlert = true
            return
        }
        
        logInfo("✅ 捕获会话设置完成，准备启动扫描", className: "ScannerViewModel")
        
        // 设置完成后立即启动扫描
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
            self?.startScanning()
        }
    }
    
    // MARK: - 扫描控制
    
    func startScanning() {
        logInfo("🔄 开始扫描", className: "ScannerViewModel")
        
        // 检查相机权限
        guard cameraAuthorizationStatus == .authorized else {
            logWarning("❌ 相机权限未授权，无法启动扫描", className: "ScannerViewModel")
            return
        }
        
        // 检查捕获会话是否已设置
        guard captureSession != nil else {
            logWarning("⚠️ 捕获会话未设置，重新设置", className: "ScannerViewModel")
            setupCaptureSession()
            return
        }
        
        // 检查会话是否已经在运行
        if captureSession.isRunning {
            logInfo("ℹ️ 扫描会话已经在运行", className: "ScannerViewModel")
            return
        }
        
        // 检查会话配置是否完整
        if captureSession.inputs.isEmpty || captureSession.outputs.isEmpty {
            logWarning("⚠️ 捕获会话配置不完整，重新设置", className: "ScannerViewModel")
            setupCaptureSession()
            return
        }
        
        logInfo("🚀 启动扫描会话", className: "ScannerViewModel")
        
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            guard let self = self else { return }
            
            self.captureSession?.startRunning()
            
            // 检查启动状态
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                if self.captureSession?.isRunning == true {
                    logInfo("✅ 扫描会话启动成功", className: "ScannerViewModel")
                } else {
                    logWarning("⚠️ 扫描会话启动失败，尝试重试", className: "ScannerViewModel")
                    // 启动失败时重试一次
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                        self.retryStartScanning()
                    }
                }
            }
        }
    }
    
    private func retryStartScanning() {
        logInfo("🔄 重试启动扫描", className: "ScannerViewModel")
        
        guard captureSession != nil else {
            logError("❌ 捕获会话为空，无法重试", className: "ScannerViewModel")
            return
        }
        
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            self?.captureSession?.startRunning()
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                if self?.captureSession?.isRunning == true {
                    logInfo("✅ 重试启动扫描成功", className: "ScannerViewModel")
                } else {
                    logError("❌ 重试启动扫描失败", className: "ScannerViewModel")
                }
            }
        }
    }
    
    func stopScanning() {
        logInfo("🔄 停止扫描", className: "ScannerViewModel")
        
        // 立即设置处理标记，防止新的检测被处理
        isProcessingDetection = true
        
        // 检查会话是否在运行
        if captureSession?.isRunning == true {
            // 立即停止扫描会话
            captureSession?.stopRunning()
            logInfo("✅ 扫描会话已停止", className: "ScannerViewModel")
        } else {
            logInfo("ℹ️ 扫描会话已经停止", className: "ScannerViewModel")
        }
    }
    
    /// 暂停相机功能（用于预览暂停状态）
    func pauseCamera() {
        logInfo("⏸️ 暂停相机功能", className: "ScannerViewModel")
        
        // 设置处理标记
        isProcessingDetection = true
        
        // 停止会话（但保留配置）
        if captureSession?.isRunning == true {
            captureSession?.stopRunning()
            logInfo("✅ 相机会话已暂停", className: "ScannerViewModel")
        } else {
            logInfo("ℹ️ 相机会话已经停止", className: "ScannerViewModel")
        }
    }
    
    /// 恢复相机功能（用于恢复扫描）
    func resumeCamera() {
        logInfo("▶️ 恢复相机功能", className: "ScannerViewModel")
        
        // 检查相机权限
        guard cameraAuthorizationStatus == .authorized else {
            logWarning("❌ 相机权限未授权，无法恢复相机", className: "ScannerViewModel")
            return
        }
        
        // 检查会话配置
        if captureSession == nil || captureSession.inputs.isEmpty || captureSession.outputs.isEmpty {
            logInfo("🔄 重新设置相机会话", className: "ScannerViewModel")
            setupCaptureSession()
        }
        
        // 重置处理标记
        isProcessingDetection = false
        
        // 启动相机会话
        if captureSession?.isRunning != true {
            logInfo("🚀 启动相机会话", className: "ScannerViewModel")
            DispatchQueue.global(qos: .userInitiated).async { [weak self] in
                self?.captureSession?.startRunning()
                
                DispatchQueue.main.async {
                    if self?.captureSession?.isRunning == true {
                        logInfo("✅ 相机会话启动成功", className: "ScannerViewModel")
                    } else {
                        logWarning("⚠️ 相机会话启动失败", className: "ScannerViewModel")
                    }
                }
            }
        }
        
        logInfo("✅ 相机功能已恢复", className: "ScannerViewModel")
    }
    

    
    func resetDetection() {
        DispatchQueue.main.async {
            logInfo("🔄 重置检测状态，清空 detectedCodes", className: "ScannerViewModel")
            self.detectedCodes = []
            self.isProcessingDetection = false  // 重置处理标记
        }
    }
    
    func isSessionRunning() -> Bool {
        return captureSession?.isRunning == true
    }
    
    func checkSessionStatus() {
        let isRunning = captureSession?.isRunning == true
        logInfo("📊 扫描会话状态检查: \(isRunning ? "运行中" : "已停止")", className: "ScannerViewModel")
        
        if !isRunning {
            logWarning("⚠️ 扫描会话未运行，尝试重新启动", className: "ScannerViewModel")
            startScanning()
        }
    }
    
    func restartScanning() {
        logInfo("🔄 重新开始扫描", className: "ScannerViewModel")
        
        // 先停止当前会话
        if captureSession?.isRunning == true {
            logInfo("🔄 停止当前运行的扫描会话", className: "ScannerViewModel")
            captureSession?.stopRunning()
        }
        
        // 重置检测状态
        resetDetection()
        
        // 延迟后重新启动会话
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            logInfo("🔄 准备重新启动扫描会话", className: "ScannerViewModel")
            
            // 在后台线程启动会话
            DispatchQueue.global(qos: .userInitiated).async { [weak self] in
                self?.captureSession?.startRunning()
                
                // 检查会话状态
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                    if self?.captureSession?.isRunning == true {
                        logInfo("✅ 扫描会话已成功重新启动", className: "ScannerViewModel")
                    } else {
                        logWarning("⚠️ 扫描会话启动失败", className: "ScannerViewModel")
                    }
                }
            }
        }
    }
    
    // MARK: - AVCaptureMetadataOutputObjectsDelegate
    
    func metadataOutput(_ output: AVCaptureMetadataOutput, 
                       didOutput metadataObjects: [AVMetadataObject], 
                       from connection: AVCaptureConnection) {
        
        // 防止重复处理检测结果
        guard !isProcessingDetection else {
            logInfo("⚠️ 正在处理检测结果，忽略新的检测", className: "ScannerViewModel")
            return
        }
        
        logInfo("metadataOutput 被调用，检测到 \(metadataObjects.count) 个对象", className: "ScannerViewModel")
        
        // 设置处理标记
        isProcessingDetection = true
        
        // 震动反馈
        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
        
        // 停止扫描
        stopScanning()
        
        // 处理所有检测到的条码
        var codes: [DetectedCode] = []
        
        for metadataObject in metadataObjects {
            if let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject,
               let stringValue = readableObject.stringValue {
                
                let codeType = getBarcodeTypeString(from: readableObject.type)
                let bounds = readableObject.bounds
                
                let detectedCode = DetectedCode(
                    type: codeType,
                    content: stringValue,
                    bounds: bounds,
                    source: .camera
                )
                
                codes.append(detectedCode)
                logInfo("创建 DetectedCode: 类型=\(codeType), 内容=\(stringValue)", className: "ScannerViewModel")
            }
        }
        
        logInfo("准备更新 detectedCodes，数量: \(codes.count)", className: "ScannerViewModel")
        
        // 更新检测到的条码列表
        DispatchQueue.main.async {
            logInfo("在主线程更新 detectedCodes", className: "ScannerViewModel")
            self.detectedCodes = codes
        }
    }
    
    // MARK: - 手电筒控制
    
    /// 检查设备是否支持手电筒
    var isTorchAvailable: Bool {
        guard let device = videoDevice else { return false }
        return device.hasTorch && device.isTorchAvailable
    }
    
    /// 切换手电筒状态
    func toggleTorch() {
        guard let device = videoDevice else {
            logWarning("❌ 没有可用的视频设备", className: "ScannerViewModel")
            return
        }
        
        guard device.hasTorch && device.isTorchAvailable else {
            logWarning("❌ 设备不支持手电筒", className: "ScannerViewModel")
            return
        }
        
        do {
            try device.lockForConfiguration()
            
            if isTorchOn {
                // 关闭手电筒
                device.torchMode = .off
                isTorchOn = false
                logInfo("🔦 手电筒已关闭", className: "ScannerViewModel")
            } else {
                // 打开手电筒
                try device.setTorchModeOn(level: 1.0)
                isTorchOn = true
                logInfo("🔦 手电筒已打开", className: "ScannerViewModel")
            }
            
            device.unlockForConfiguration()
            
        } catch {
            logError("❌ 手电筒控制失败: \(error.localizedDescription)", className: "ScannerViewModel")
            device.unlockForConfiguration()
        }
    }
    
    /// 关闭手电筒
    func turnOffTorch() {
        guard let device = videoDevice else { return }
        
        do {
            try device.lockForConfiguration()
            device.torchMode = .off
            isTorchOn = false
            device.unlockForConfiguration()
            logInfo("🔦 手电筒已关闭", className: "ScannerViewModel")
        } catch {
            logError("❌ 关闭手电筒失败: \(error.localizedDescription)", className: "ScannerViewModel")
            device.unlockForConfiguration()
        }
    }
    
    // MARK: - 条形码类型转换
    
    /// 获取条形码类型的可读字符串
    private func getBarcodeTypeString(from metadataType: AVMetadataObject.ObjectType) -> String {
        switch metadataType {
        case .ean8:
            return "EAN-8"
        case .ean13:
            return "EAN-13"
        case .upce:
            return "UPC-E"
        case .code39:
            return "Code 39"
        case .code93:
            return "Code 93"
        case .code128:
            return "Code 128"
        case .itf14:
            return "ITF-14"
        case .pdf417:
            return "PDF417"
        case .qr:
            return "QR Code"
        case .dataMatrix:
            return "Data Matrix"
        case .aztec:
            return "Aztec"
        default:
            // 处理可能包含前缀的类型字符串
            let typeString = metadataType.rawValue
            if typeString.contains("org.gs1.") {
                // 移除 org.gs1. 前缀
                let cleanType = typeString.replacingOccurrences(of: "org.gs1.", with: "")
                return cleanType.uppercased()
            }
            return typeString
        }
    }
} 