import Foundation

// MARK: - Agent 模型配置（对应 models.json）

struct AgentModelConfig: Codable, Identifiable {
    var id: String { name }
    var url: String
    var name: String
    var apikey: String
    var modes: String
    var multimodal: String
    var maxOutput: Int
    var maxContext: Int

    init(url: String = "", name: String = "", apikey: String = "",
         modes: String = "快速,思考", multimodal: String = "", maxOutput: Int = 32000, maxContext: Int = 256000) {
        self.url = url
        self.name = name
        self.apikey = apikey
        self.modes = modes
        self.multimodal = multimodal
        self.maxOutput = maxOutput
        self.maxContext = maxContext
    }

    /// 是否支持思考模式
    var supportsThinking: Bool { modes.contains("思考") || modes.contains("thinking") }
    /// 是否支持快速模式
    var supportsFast: Bool { modes.contains("快速") || modes.contains("fast") }
    /// 脱敏显示 API Key
    var maskedKey: String {
        apikey.count <= 8 ? apikey : "\(apikey.prefix(3))...\(apikey.suffix(3))"
    }
}

struct AgentModelsFile: Codable {
    var tavilyApiKey: String
    var defaultModel: String
    var models: [AgentModelConfig]
}

enum RecognitionLanguage: String, CaseIterable {
    case chineseSimplified  = "zh-CN"
    case english            = "en-US"
    case chineseTraditional = "zh-TW"
    case japanese           = "ja-JP"
    case korean             = "ko-KR"

    var displayName: String {
        switch self {
        case .chineseSimplified:  return "简体中文"
        case .english:            return "English"
        case .chineseTraditional: return "繁體中文"
        case .japanese:           return "日本語"
        case .korean:             return "한국어"
        }
    }
}

enum LLMMode {
    case input    // 语音输入纠错
    case assist   // AI 助手对话
    case agent    // 智能体调用
}

enum TriggerMode: String {
    case input  = "input"   // 语音输入
    case assist = "assist"  // AI 助手
    case agent  = "agent"   // 智能体调用
}

enum AgentReminderMode: String, CaseIterable {
    case agent  = "agent"
    case system = "system"
    case both   = "both"

    var displayName: String {
        switch self {
        case .agent:  return "智能体通知"
        case .system: return "系统通知"
        case .both:   return "同时通知"
        }
    }
}

enum AssistOutputMode: String, CaseIterable {
    case inject = "inject"  // 直接输入到输入栏
    case notch  = "notch"    // 刘海弹窗展示

    var displayName: String {
        switch self {
        case .inject: return "直接输入"
        case .notch:  return "刘海弹窗"
        }
    }
}

struct LLMConfig {
    var enabled: Bool
    var baseURL: String
    var apiKey: String
    var model: String
    
    var isConfigured: Bool {
        !baseURL.isEmpty && !apiKey.isEmpty && !model.isEmpty
    }
}

final class Config {
    static let shared = Config()
    
    private init() {}

    private let defaults = UserDefaults.standard

    private enum Keys {
        static let language = "recognition_language"
        static let triggerMode = "trigger_mode"
        
        // 输入模式 LLM（语音输入纠错）
        static let inputLLMEnabled = "input_llm_enabled"
        static let inputLLMBaseURL = "input_llm_base_url"
        static let inputLLMAPIKey = "input_llm_api_key"
        static let inputLLMModel = "input_llm_model"
        
        // 助手模式 LLM（AI 助手对话）
        static let assistLLMEnabled = "assist_llm_enabled"
        static let assistLLMBaseURL = "assist_llm_base_url"
        static let assistLLMAPIKey = "assist_llm_api_key"
        static let assistLLMModel = "assist_llm_model"
        
        // 助手模式输出方式
        static let assistOutputMode = "assist_output_mode"

        // 助手模式朗读开关
        static let assistSpeakEnabled = "assist_speak_enabled"

        // 智能体模式朗读开关
        static let agentSpeakEnabled = "agent_speak_enabled"

        // 智能体模式
        static let agentLLMEnabled = "agent_llm_enabled"
        static let agentLLMBaseURL = "agent_llm_base_url"
        static let agentLLMAPIKey = "agent_llm_api_key"
        static let agentLLMModel = "agent_llm_model"
        static let agentWorkspace = "agent_workspace"
    }

    var language: RecognitionLanguage {
        get {
            guard let raw = defaults.string(forKey: Keys.language),
                  let lang = RecognitionLanguage(rawValue: raw) else {
                return .chineseSimplified
            }
            return lang
        }
        set {
            defaults.set(newValue.rawValue, forKey: Keys.language)
        }
    }

    // MARK: - 触发模式（菜单栏切换）
    
    var triggerMode: TriggerMode {
        get {
            guard let raw = defaults.string(forKey: Keys.triggerMode),
                  let mode = TriggerMode(rawValue: raw) else {
                return .input
            }
            return mode
        }
        set {
            defaults.set(newValue.rawValue, forKey: Keys.triggerMode)
        }
    }

    // MARK: - 输入模式配置（语音输入纠错）
    
    var inputLLM: LLMConfig {
        get {
            LLMConfig(
                enabled: defaults.bool(forKey: Keys.inputLLMEnabled),
                baseURL: defaults.string(forKey: Keys.inputLLMBaseURL) ?? "",
                apiKey: defaults.string(forKey: Keys.inputLLMAPIKey) ?? "",
                model: defaults.string(forKey: Keys.inputLLMModel) ?? ""
            )
        }
        set {
            defaults.set(newValue.enabled, forKey: Keys.inputLLMEnabled)
            defaults.set(newValue.baseURL, forKey: Keys.inputLLMBaseURL)
            defaults.set(newValue.apiKey, forKey: Keys.inputLLMAPIKey)
            defaults.set(newValue.model, forKey: Keys.inputLLMModel)
        }
    }
    
    // 兼容旧版本
    var llmEnabled: Bool {
        get { inputLLM.enabled }
        set { 
            var cfg = inputLLM
            cfg.enabled = newValue
            inputLLM = cfg
        }
    }
    
    var llmBaseURL: String {
        get { inputLLM.baseURL }
        set {
            var cfg = inputLLM
            cfg.baseURL = newValue
            inputLLM = cfg
        }
    }
    
    var llmAPIKey: String {
        get { inputLLM.apiKey }
        set {
            var cfg = inputLLM
            cfg.apiKey = newValue
            inputLLM = cfg
        }
    }
    
    var llmModel: String {
        get { inputLLM.model }
        set {
            var cfg = inputLLM
            cfg.model = newValue
            inputLLM = cfg
        }
    }
    
    var isLLMConfigured: Bool { inputLLM.isConfigured }

    // MARK: - Control 键模式配置（AI 助手）
    
    var assistLLM: LLMConfig {
        get {
            LLMConfig(
                enabled: defaults.bool(forKey: Keys.assistLLMEnabled),
                baseURL: defaults.string(forKey: Keys.assistLLMBaseURL) ?? "",
                apiKey: defaults.string(forKey: Keys.assistLLMAPIKey) ?? "",
                model: defaults.string(forKey: Keys.assistLLMModel) ?? ""
            )
        }
        set {
            defaults.set(newValue.enabled, forKey: Keys.assistLLMEnabled)
            defaults.set(newValue.baseURL, forKey: Keys.assistLLMBaseURL)
            defaults.set(newValue.apiKey, forKey: Keys.assistLLMAPIKey)
            defaults.set(newValue.model, forKey: Keys.assistLLMModel)
        }
    }

    // MARK: - 助手模式输出方式

    var assistOutputMode: AssistOutputMode {
        get {
            guard let raw = defaults.string(forKey: Keys.assistOutputMode),
                  let mode = AssistOutputMode(rawValue: raw) else {
                return .inject
            }
            return mode
        }
        set {
            defaults.set(newValue.rawValue, forKey: Keys.assistOutputMode)
        }
    }

    // MARK: - 助手模式朗读开关

    var assistSpeakEnabled: Bool {
        get { defaults.bool(forKey: Keys.assistSpeakEnabled) }
        set { defaults.set(newValue, forKey: Keys.assistSpeakEnabled) }
    }

    // MARK: - 智能体模式配置

    var agentLLM: LLMConfig {
        get {
            LLMConfig(
                enabled: defaults.bool(forKey: Keys.agentLLMEnabled),
                baseURL: defaults.string(forKey: Keys.agentLLMBaseURL) ?? "",
                apiKey: defaults.string(forKey: Keys.agentLLMAPIKey) ?? "",
                model: defaults.string(forKey: Keys.agentLLMModel) ?? ""
            )
        }
        set {
            defaults.set(newValue.enabled, forKey: Keys.agentLLMEnabled)
            defaults.set(newValue.baseURL, forKey: Keys.agentLLMBaseURL)
            defaults.set(newValue.apiKey, forKey: Keys.agentLLMAPIKey)
            defaults.set(newValue.model, forKey: Keys.agentLLMModel)
        }
    }

    var agentWorkspace: String {
        get { defaults.string(forKey: Keys.agentWorkspace) ?? NSHomeDirectory() }
        set { defaults.set(newValue, forKey: Keys.agentWorkspace) }
    }

    var agentSpeakEnabled: Bool {
        get { defaults.bool(forKey: Keys.agentSpeakEnabled) }
        set { defaults.set(newValue, forKey: Keys.agentSpeakEnabled) }
    }

    // Agent 运行模式
    var agentAllowMode: String {
        get { defaults.string(forKey: "agent_allow_mode") ?? "full_access" }
        set { defaults.set(newValue, forKey: "agent_allow_mode") }
    }

    // Agent 输入方式
    var agentInputMode: String {
        get { defaults.string(forKey: "agent_input_mode") ?? "voice" }
        set { defaults.set(newValue, forKey: "agent_input_mode") }
    }

    // Agent 思考模式
    var agentThinkingMode: Bool {
        get { defaults.bool(forKey: "agent_thinking_mode") }
        set { defaults.set(newValue, forKey: "agent_thinking_mode") }
    }

    // Agent 待办提醒通知方式
    var agentReminderMode: AgentReminderMode {
        get {
            guard let raw = defaults.string(forKey: "agent_reminder_mode"),
                  let mode = AgentReminderMode(rawValue: raw) else {
                return .agent
            }
            return mode
        }
        set { defaults.set(newValue.rawValue, forKey: "agent_reminder_mode") }
    }

    // MARK: - 助手个性化配置

    var assistantName: String {
        get { defaults.string(forKey: "assistant_name") ?? "小助手" }
        set {
            defaults.set(newValue, forKey: "assistant_name")
            saveUserProfile()
        }
    }

    var assistantTone: String {
        get { defaults.string(forKey: "assistant_tone") ?? "友好" }
        set {
            defaults.set(newValue, forKey: "assistant_tone")
            saveUserProfile()
        }
    }

    var userName: String {
        get { defaults.string(forKey: "user_name") ?? "" }
        set {
            defaults.set(newValue, forKey: "user_name")
            saveUserProfile()
        }
    }

    var agentShowTools: Bool {
        get {
            if defaults.object(forKey: "agent_show_tools") == nil { return true }
            return defaults.bool(forKey: "agent_show_tools")
        }
        set { defaults.set(newValue, forKey: "agent_show_tools") }
    }

    var agentToolsMode: String {
        get { defaults.string(forKey: "agent_tools_mode") ?? "all" }
        set { defaults.set(newValue, forKey: "agent_tools_mode") }
    }

    var agentNewConversationMode: String {
        get { defaults.string(forKey: "agent_new_conversation_mode") ?? "manual" }
        set { defaults.set(newValue, forKey: "agent_new_conversation_mode") }
    }

    /// 自动新建对话的 token 阈值（仅 newConversationMode == "auto" 时生效）
    var agentAutoNewTokenThreshold: Int {
        get {
            let val = defaults.integer(forKey: "agent_auto_new_token_threshold")
            return val > 0 ? val : 40000
        }
        set { defaults.set(newValue, forKey: "agent_auto_new_token_threshold") }
    }

    /// 语音输入后是否自动发送（false 时只填入输入框）
    var agentVoiceAutoSend: Bool {
        get {
            if defaults.object(forKey: "agent_voice_auto_send") == nil { return true }
            return defaults.bool(forKey: "agent_voice_auto_send")
        }
        set { defaults.set(newValue, forKey: "agent_voice_auto_send") }
    }

    // MARK: - 用户配置文件（user_profile.json）

    /// Agent 目录路径：优先查找 bundle Resources，其次逐级往上搜索包含 models.json 的 Agent/
    var agentDir: String {
        // 优先级 0：bundle Resources/Agent（Release 打包后）
        if let resourcePath = Bundle.main.resourcePath {
            let bundledAgent = resourcePath + "/Agent/models.json"
            if FileManager.default.fileExists(atPath: bundledAgent) {
                print("[Config] found Agent in bundle Resources: \(resourcePath)/Agent")
                return resourcePath + "/Agent"
            }
        }

        // 优先级 1：从 bundlePath 开始逐级往上搜索（Debug 开发模式）
        var dir = Bundle.main.bundlePath
        print("[Config] bundlePath: \(Bundle.main.bundlePath)")
        for i in 0..<6 {
            let candidate = dir + "/Agent/models.json"
            let exists = FileManager.default.fileExists(atPath: candidate)
            print("[Config]   level \(i): \(candidate) → \(exists ? "YES" : "NO")")
            if exists {
                return dir + "/Agent"
            }
            dir = (dir as NSString).deletingLastPathComponent
        }
        // 回退：当前工作目录
        let cwd = FileManager.default.currentDirectoryPath + "/Agent/models.json"
        print("[Config]   cwd: \(cwd) → \(FileManager.default.fileExists(atPath: cwd) ? "YES" : "NO")")
        if FileManager.default.fileExists(atPath: cwd) {
            return FileManager.default.currentDirectoryPath + "/Agent"
        }
        // 最后回退到开发默认路径
        return Bundle.main.bundlePath + "/../../../Agent"
    }

    var agentModelsPath: String { agentDir + "/models.json" }

    /// 用户数据目录（配置持久化，覆盖安装不丢失）
    private var userDataDir: String {
        let appSupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
        let dir = appSupport.appendingPathComponent("VoiceInput").path
        // 确保目录存在
        if !FileManager.default.fileExists(atPath: dir) {
            try? FileManager.default.createDirectory(atPath: dir, withIntermediateDirectories: true)
        }
        return dir
    }

    /// 用户目录下的 models.json（覆盖安装不丢失）
    var userAgentModelsPath: String {
        userDataDir + "/models.json"
    }

    /// 用户配置文件路径（助手名字/语气）
    var userProfilePath: String {
        userDataDir + "/user_profile.json"
    }

    /// 记忆文件路径
    var memoryPath: String {
        userDataDir + "/memory/memory.json"
    }

    // MARK: - models.json 读写

    func loadAgentModels() -> AgentModelsFile {
        let userPath = userAgentModelsPath

        // 用户目录已有配置 → 直接读取
        if FileManager.default.fileExists(atPath: userPath),
           let data = try? Data(contentsOf: URL(fileURLWithPath: userPath)) {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            if let models = try? decoder.decode(AgentModelsFile.self, from: data) {
                return models
            }
        }

        // 首次启动：从 bundle 模板复制到用户目录
        let bundlePath = agentModelsPath
        if FileManager.default.fileExists(atPath: bundlePath),
           let data = try? Data(contentsOf: URL(fileURLWithPath: bundlePath)) {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            if let models = try? decoder.decode(AgentModelsFile.self, from: data) {
                // 复制到用户目录
                try? data.write(to: URL(fileURLWithPath: userPath), options: .atomic)
                return models
            }
        }

        return AgentModelsFile(tavilyApiKey: "", defaultModel: "", models: [])
    }

    func saveAgentModels(_ models: AgentModelsFile) {
        let path = userAgentModelsPath
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase
        guard let data = try? encoder.encode(models) else { return }
        try? data.write(to: URL(fileURLWithPath: path), options: .atomic)
    }

    /// 保存用户个性化配置到 user_profile.json
    func saveUserProfile() {
        let profile: [String: String] = [
            "assistant_name": assistantName,
            "assistant_tone": assistantTone,
            "user_name": userName,
        ]
        let encoder = JSONEncoder()
        guard let data = try? encoder.encode(profile) else { return }
        try? data.write(to: URL(fileURLWithPath: userProfilePath), options: .atomic)
    }

    /// 从 user_profile.json 同步到 UserDefaults（用于窗口打开时刷新）
    func syncUserProfile() {
        guard let data = try? Data(contentsOf: URL(fileURLWithPath: userProfilePath)),
              let profile = try? JSONDecoder().decode([String: String].self, from: data) else {
            return
        }
        if let name = profile["assistant_name"], !name.isEmpty {
            defaults.set(name, forKey: "assistant_name")
        }
        if let tone = profile["assistant_tone"], !tone.isEmpty {
            defaults.set(tone, forKey: "assistant_tone")
        }
        if let userName = profile["user_name"], !userName.isEmpty {
            defaults.set(userName, forKey: "user_name")
        }
    }

    /// 有效的模型列表（过滤掉配置不完整的）
    var validAgentModels: [AgentModelConfig] {
        loadAgentModels().models.filter { m in
            !m.url.isEmpty && !m.name.isEmpty && !m.apikey.isEmpty && !m.modes.isEmpty
        }
    }

    func getLLMConfig(for mode: LLMMode) -> LLMConfig {
        switch mode {
        case .input: return inputLLM
        case .assist: return assistLLM
        case .agent: return agentLLM
        }
    }

    func setLLMConfig(_ config: LLMConfig, for mode: LLMMode) {
        switch mode {
        case .input: inputLLM = config
        case .assist: assistLLM = config
        case .agent: agentLLM = config
        }
    }
}
