import Cocoa

/// 应用主控制器，协调 Fn 键（语音输入）和 Control 键（AI 助手）两种模式
final class AppDelegate: NSObject, NSApplicationDelegate {

    private let keyMonitor = KeyMonitor()
    private let speechRecognizer = SpeechRecognizer()
    private let audioMonitor = AudioLevelMonitor()
    private let recordingPanel = RecordingPanel()
    private let menuBarController = MenuBarController()
    private let llmRefiner = LLMRefiner()

    private var isRecording = false
    private var finalTranscription: String = ""
    private var currentMode: LLMMode = .input

    func applicationDidFinishLaunching(_ notification: Notification) {
        NSApp.setActivationPolicy(.accessory)

        // 检查辅助功能权限
        if !CGPreflightListenEventAccess() {
            requestAccessibilityPermission()
        } else {
            startKeyMonitor()
        }

        print("[App] Ready")
    }

    // MARK: - Permissions

    private func requestAccessibilityPermission() {
        NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")!)

        let alert = NSAlert()
        alert.messageText = "需要辅助功能权限"
        alert.informativeText = """
        Voice Input 需要「辅助功能」权限才能监听 Fn 键和 Control 键。

        系统设置已自动打开，请：
        1. 点击左下角的锁并输入密码
        2. 在列表中找到并勾选「VoiceInput」
        3. 返回本应用

        点击「继续」后，应用将每 2 秒检查一次权限状态。
        """
        alert.alertStyle = .informational
        alert.addButton(withTitle: "继续")
        alert.addButton(withTitle: "退出")

        if alert.runModal() == .alertFirstButtonReturn {
            Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { [weak self] timer in
                if CGPreflightListenEventAccess() {
                    timer.invalidate()
                    DispatchQueue.main.async {
                        self?.startKeyMonitor()
                        let successAlert = NSAlert()
                        successAlert.messageText = "权限已授权"
                        successAlert.informativeText = "辅助功能权限已开启，Voice Input 正在运行。"
                        successAlert.alertStyle = .informational
                        successAlert.runModal()
                    }
                }
            }
        } else {
            NSApp.terminate(nil)
        }
    }

    private func startKeyMonitor() {
        let started = keyMonitor.start()
        if !started {
            print("[App] Failed to start key monitor")
            return
        }

        // Fn 键：语音输入模式
        keyMonitor.onFnDown = { [weak self] in
            self?.currentMode = .input
            self?.startRecording()
        }
        keyMonitor.onFnUp = { [weak self] in
            self?.stopRecording()
        }

        // Control 键：AI 助手模式
        keyMonitor.onControlDown = { [weak self] in
            self?.currentMode = .assist
            self?.startRecording()
        }
        keyMonitor.onControlUp = { [weak self] in
            self?.stopRecording()
        }
    }

    // MARK: - Recording

    private func startRecording() {
        guard !isRecording else { return }
        isRecording = true
        finalTranscription = ""

        recordingPanel.showAnimated()
        
        // 根据模式显示不同提示
        let promptText = currentMode == .input ? "Listening..." : "Ask AI..."
        recordingPanel.updateText(promptText)

        let language = Config.shared.language.rawValue

        Task { @MainActor in
            let audioOK = audioMonitor.start()
            if audioOK {
                audioMonitor.onLevelUpdate = { [weak self] level in
                    self?.recordingPanel.waveformView.updateLevel(level)
                }
            }

            let speechOK = await speechRecognizer.start(language: language)
            if !speechOK {
                recordingPanel.updateText("Recognition error")
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
                    self?.cancelRecording()
                }
                return
            }

            speechRecognizer.onResult = { [weak self] text in
                guard let self = self, self.isRecording else { return }
                self.finalTranscription = text
                self.recordingPanel.updateText(text)
            }

            speechRecognizer.onError = { error in
                let nsError = error as NSError
                if nsError.domain == "kAFAssistantErrorDomain" && nsError.code == 1110 {
                    return
                }
                print("[App] Speech error: \(error)")
            }
        }
    }

    private func stopRecording() {
        guard isRecording else { return }
        isRecording = false

        audioMonitor.stop()
        _ = speechRecognizer.stop()

        let text = finalTranscription.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else {
            recordingPanel.hideAnimated()
            finalTranscription = ""
            return
        }

        let config = Config.shared.getLLMConfig(for: currentMode)

        switch currentMode {
        case .input:
            // Fn 键模式：语音输入 + 纠错
            handleInputMode(text: text, config: config)
        case .assist:
            // Control 键模式：AI 助手对话
            handleAssistMode(text: text, config: config)
        }

        finalTranscription = ""
    }

    // MARK: - Input Mode (Fn)

    private func handleInputMode(text: String, config: LLMConfig) {
        guard config.enabled && config.isConfigured else {
            recordingPanel.hideAnimated {
                TextInjector.inject(text)
            }
            return
        }

        recordingPanel.showRefining()

        Task { @MainActor in
            do {
                let result = try await llmRefiner.refine(text: text, config: config)
                recordingPanel.hideAnimated {
                    TextInjector.inject(result.text)
                }
            } catch {
                print("[App] LLM refine error: \(error)")
                recordingPanel.hideAnimated {
                    TextInjector.inject(text)
                }
            }
        }
    }

    // MARK: - Assist Mode (Control)

    private func handleAssistMode(text: String, config: LLMConfig) {
        guard config.enabled && config.isConfigured else {
            recordingPanel.updateText("AI 助手未配置")
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
                self?.recordingPanel.hideAnimated()
            }
            return
        }

        recordingPanel.showThinking()

        Task { @MainActor in
            do {
                let result = try await llmRefiner.chat(text: text, config: config)
                recordingPanel.hideAnimated {
                    TextInjector.inject(result.text)
                }
            } catch {
                print("[App] LLM chat error: \(error)")
                recordingPanel.updateText("请求失败，请检查配置")
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { [weak self] in
                    self?.recordingPanel.hideAnimated()
                }
            }
        }
    }

    private func cancelRecording() {
        audioMonitor.stop()
        speechRecognizer.cancel()
        recordingPanel.hideAnimated()
        isRecording = false
        finalTranscription = ""
    }

    func applicationWillTerminate(_ notification: Notification) {
        keyMonitor.stop()
        audioMonitor.stop()
        speechRecognizer.cancel()
        recordingPanel.close()
    }
}
