//
//  PhoneService.swift
//  JJPhoneDemo
//
//  电话服务层 - 封装 VoIPManagerFramework 的功能
//  提供统一的接口供 UI 层使用，实现 UI 与 Service 分离
//

import Foundation
import AVFoundation

/// 电话服务协议，抽象电话相关能力，便于 UI 与底层解耦
protocol PhoneServiceProtocol {
    /// 初始化服务
    func initialize() -> Int
    
    /// 登出 SIP
    func logout()
    
    /// 拨打电话
    func makeCall(number: String, userData: [String: Any]?)
    
    /// 挂断电话
    func hangupCall()
    
    /// 接听电话
    func acceptCall()
    
    /// 发送 DTMF
    func sendDTMF(number: String)
    
    /// 设置静音
    func setMute(_ mute: Bool)
    
    /// 设置免提
    func setLoudSpeaker(_ loud: Bool)
    
    /// 检查是否可以拨打电话
    func canMakeCall() -> Bool
    
    /// 通话接通后，确保音频会话正确配置并激活
    func ensureAudioSessionForCall()
    
    /// 获取错误描述
    static func errorDescription(forCode code: Int) -> String
}

/// 电话服务实现类（单例），封装 VoIPManager 能力
class PhoneService: PhoneServiceProtocol {
    
    /// 共享实例
    static let shared = PhoneService()
    
    /// 底层 VoIP 管理器
    private let voipManager = VoIPManager.shared()
    
    /// 私有初始化，确保单例模式
    private init() {
        setupMessageHandler()
    }
    
    private func setupMessageHandler() {
        voipManager.messageHandler = { message in
            AppLogger.debug(message, category: "PhoneService")
        }
    }
    
    /// 配置 AVAudioSession（在 PJSIP 初始化之前调用）
    private func configureAudioSession() {
        do {
            let audioSession = AVAudioSession.sharedInstance()
            
            // 先请求麦克风权限（同步等待，确保权限已授予）
            var permissionGranted = false
            let semaphore = DispatchSemaphore(value: 0)
            
            audioSession.requestRecordPermission { granted in
                permissionGranted = granted
                if !granted {
                    AppLogger.warning("Microphone permission denied", category: "PhoneService")
                }
                semaphore.signal()
            }
            
            // 等待权限请求完成（最多等待 2 秒）
            _ = semaphore.wait(timeout: .now() + 2.0)
            
            if !permissionGranted {
                AppLogger.warning("Microphone permission not granted, audio may not work", category: "PhoneService")
            }
            
            // 配置音频会话类别（必须在激活之前）
            // 默认使用听筒模式，不设置 .defaultToSpeaker
            try audioSession.setCategory(
                .playAndRecord,
                mode: .voiceChat,
                options: [.allowBluetooth, .allowBluetoothA2DP, .duckOthers]
            )
            
            // 激活音频会话
            try audioSession.setActive(true, options: [])
            
        } catch {
            AppLogger.error("AVAudioSession configuration failed - \(error.localizedDescription)", category: "PhoneService")
        }
    }
    
    func initialize() -> Int {
        if Thread.isMainThread {
            configureAudioSession()
        } else {
            DispatchQueue.main.sync {
                configureAudioSession()
            }
        }
        
        let result = voipManager.initial()
                
        return Int(result.rawValue)
    }
    
    /// 确保音频会话处于活动状态
    private func ensureAudioSessionActive() {
        do {
            let audioSession = AVAudioSession.sharedInstance()
            
            // 检查当前类别是否正确
            if audioSession.category != .playAndRecord || audioSession.mode != .voiceChat {
                try audioSession.setCategory(
                    .playAndRecord,
                    mode: .voiceChat,
                    options: [.allowBluetooth, .allowBluetoothA2DP, .duckOthers]
                )
            }
            
            // 激活音频会话
            try audioSession.setActive(true, options: [])
        } catch {
            AppLogger.error("Failed to activate audio session - \(error.localizedDescription)", category: "PhoneService")
        }
    }
    
    /// 通话接通后，确保音频会话正确配置并激活（应在 sipCallConfirm 通知后调用）
    func ensureAudioSessionForCall() {
        if Thread.isMainThread {
            ensureAudioSessionActiveForCall()
        } else {
            DispatchQueue.main.sync {
                ensureAudioSessionActiveForCall()
            }
        }
    }
    
    private func ensureAudioSessionActiveForCall() {
        do {
            let audioSession = AVAudioSession.sharedInstance()
            
            if audioSession.category != .playAndRecord || audioSession.mode != .voiceChat {
                try audioSession.setCategory(
                    .playAndRecord,
                    mode: .voiceChat,
                    options: [.allowBluetooth, .allowBluetoothA2DP, .duckOthers]
                )
            }
            
            try audioSession.setActive(true, options: [.notifyOthersOnDeactivation])
            
            let outputVolume = audioSession.outputVolume
            if outputVolume < 0.5 {
                AppLogger.warning("System volume is low (\(String(format: "%.0f%%", outputVolume * 100)))", category: "PhoneService")
            }
            
        } catch {
            AppLogger.error("Failed to activate audio session for call - \(error.localizedDescription)", category: "PhoneService")
        }
    }
    /// 完整的登录流程：登录 -> 连接 Socket -> 获取 SIP 信息 -> 登录 SIP
    /// - Parameters:
    ///   - account: 登录账号（格式：用户名@域名，如：6000@exd）
    ///   - password: 登录密码
    ///   - environment: 环境类型（生产环境或开发环境）
    ///   - passwordPk: 可选的已加密密码
    ///   - statusUpdate: 状态更新回调（用于显示登录进度）
    ///   - success: 成功回调
    ///   - failure: 失败回调
    func loginWithAccount(account: String,
                         password: String,
                         environment: VoIPEnvironment,
                         passwordPk: String?,
                         statusUpdate: @escaping (String) -> Void,
                         success: @escaping ([String: Any]) -> Void,
                         failure: @escaping (Int, String?) -> Void) {
        let maskedAccount: String
        if let atRange = account.range(of: "@") {
            let userPart = String(account[..<atRange.lowerBound])
            let domainPart = String(account[atRange.upperBound...])
            let maskedUser = userPart.isEmpty ? "" : String(repeating: "*", count: max(1, min(4, userPart.count)))
            maskedAccount = maskedUser + "@" + domainPart
        } else {
            maskedAccount = String(repeating: "*", count: min(4, max(1, account.count)))
        }
        AppLogger.info("Starting login process for account: \(maskedAccount), environment: \(environment == .production ? "production" : "development")", category: "PhoneService")
        
        // 设置 messageHandler 来接收状态更新
        let originalHandler: ((String) -> Void)? = voipManager.messageHandler
        
        voipManager.messageHandler = { message in
            DispatchQueue.main.async {
                statusUpdate(message)
            }
            if let handler = originalHandler {
                handler(message)
            }
        }
        
        // 恢复 handler 的辅助函数
        let restoreHandler: () -> Void = { [weak self] in
            guard let self = self else { return }
            if let handler = originalHandler {
                self.voipManager.messageHandler = handler
            } else {
                // 恢复为默认的 handler
                self.setupMessageHandler()
            }
        }
        
        // 确保在主线程调用
        if Thread.isMainThread {
            voipManager.login(withAccount: account,
                            password: password,
                            environment: environment,
                            passwordPk: passwordPk,
                            success: { result in
                                AppLogger.info("Login process completed successfully", category: "PhoneService")
                                restoreHandler()
                                // 将 NSDictionary 转换为 [String: Any]
                                var stringDict: [String: Any] = [:]
                                if let dict = result as? [AnyHashable: Any] {
                                    for (key, value) in dict {
                                        if let stringKey = key as? String {
                                            stringDict[stringKey] = value
                                        }
                                    }
                                }
                                success(stringDict)
                            },
                            failure: { code, message in
                                AppLogger.error("Login failed - code: \(code), message: \(message ?? "unknown")", category: "PhoneService")
                                restoreHandler()
                                failure(Int(code), message)
                            })
        } else {
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.voipManager.login(withAccount: account,
                                      password: password,
                                      environment: environment,
                                      passwordPk: passwordPk,
                            success: { result in
                                AppLogger.info("Login process completed successfully", category: "PhoneService")
                                restoreHandler()
                                // 将 NSDictionary 转换为 [String: Any]
                                var stringDict: [String: Any] = [:]
                                if let dict = result as? [AnyHashable: Any] {
                                    for (key, value) in dict {
                                        if let stringKey = key as? String {
                                            stringDict[stringKey] = value
                                        }
                                    }
                                }
                                success(stringDict)
                            },
                                      failure: { code, message in
                                          AppLogger.error("登录流程失败: code=\(code), message=\(message ?? "无")", category: "PhoneService")
                                          restoreHandler()
                                          failure(Int(code), message)
                                      })
            }
        }
    }
    
    func logout() {
        voipManager.logout()
    }
    
    func makeCall(number: String, userData: [String: Any]? = nil) {
        // 确保音频会话在拨打电话前处于活动状态（在主线程执行）
//        if Thread.isMainThread {
//            ensureAudioSessionActive()
//        } else {
//            DispatchQueue.main.sync {
//                ensureAudioSessionActive()
//            }
//        }
        
        // 如果有自定义数据，使用带 userData 的方法
        if let userData = userData {
            // Swift 字典会自动桥接到 NSDictionary
            voipManager.makeCall(number,
                                userData: userData as [AnyHashable : Any],
                                success: { callId in
                                    AppLogger.info("Call initiated successfully with callId: \(callId), userData: \(userData)", category: "PhoneService")
                                },
                                failure: { code, message in
                                    AppLogger.error("Call failed - code: \(code), message: \(message ?? "unknown")", category: "PhoneService")
                                })
        } else {
            // 没有自定义数据，使用普通方法
            voipManager.makeCall(number,
                                success: { callId in
                                    AppLogger.info("Call initiated successfully with callId: \(callId)", category: "PhoneService")
                                },
                                failure: { code, message in
                                    AppLogger.error("Call failed - code: \(code), message: \(message ?? "unknown")", category: "PhoneService")
                                })
        }
    }
    
    func hangupCall() {
        voipManager.hangupCall()
    }
    
    func acceptCall() {
        // 确保音频会话在接听电话前处于活动状态（在主线程执行）
        if Thread.isMainThread {
            ensureAudioSessionActive()
        } else {
            DispatchQueue.main.sync {
                ensureAudioSessionActive()
            }
        }
        voipManager.acceptCall()
    }
    
    func sendDTMF(number: String) {
        voipManager.sendDTMF(number)
    }
    
    func setMute(_ mute: Bool) {
        AppLogger.debug("调用 Framework openMute(\(mute))", category: "PhoneService")
        voipManager.openMute(mute)
        AppLogger.debug("Framework openMute 调用完成", category: "PhoneService")
    }
    
    func setLoudSpeaker(_ loud: Bool) {
        voipManager.openLoudSpeaker(loud)
    }
    
    func canMakeCall() -> Bool {
        return voipManager.canMakeCall()
    }
    
    static func errorDescription(forCode code: Int) -> String {
        return VoIPManager.errorDescription(forCode: code)
    }
}

