import AVFoundation
import Foundation

enum VoiceMessageRecorderError: LocalizedError {
    case permissionDenied
    case failedToStart

    var errorDescription: String? {
        switch self {
        case .permissionDenied: return "无法录音：未获得麦克风权限"
        case .failedToStart: return "无法开始录音"
        }
    }
}

@MainActor
final class VoiceMessageRecorder {
    private var recorder: AVAudioRecorder?
    private var startedAt: Date?
    private(set) var isRecording = false

    var elapsedSeconds: Int {
        guard let startedAt else { return 0 }
        return max(0, Int(Date().timeIntervalSince(startedAt)))
    }

    func start() async throws {
        if isRecording { return }

        let session = AVAudioSession.sharedInstance()
        switch session.recordPermission {
        case .granted:
            break
        case .denied:
            throw VoiceMessageRecorderError.permissionDenied
        case .undetermined:
            let granted = await withCheckedContinuation { continuation in
                session.requestRecordPermission { continuation.resume(returning: $0) }
            }
            guard granted else { throw VoiceMessageRecorderError.permissionDenied }
        @unknown default:
            throw VoiceMessageRecorderError.permissionDenied
        }

        try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth])
        try session.setActive(true)

        let dir = ChatHistoryStore.rootURL.appendingPathComponent("attachments", isDirectory: true)
        try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
        let url = dir.appendingPathComponent("voice_\(Int(Date().timeIntervalSince1970 * 1_000)).m4a")

        let settings: [String: Any] = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 44_100,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
        ]

        let recorder = try AVAudioRecorder(url: url, settings: settings)
        recorder.isMeteringEnabled = true
        guard recorder.record() else { throw VoiceMessageRecorderError.failedToStart }

        self.recorder = recorder
        startedAt = Date()
        isRecording = true
    }

    func stop() -> (path: String, durationSec: Double)? {
        guard isRecording, let recorder else { return nil }
        recorder.stop()
        isRecording = false
        let duration = max(1, recorder.currentTime)
        let path = ChatHistoryHelper.relativeAttachmentPath(for: recorder.url)
        self.recorder = nil
        startedAt = nil
        try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
        return (path, duration)
    }

    func cancel() {
        guard let recorder else { return }
        recorder.stop()
        try? FileManager.default.removeItem(at: recorder.url)
        self.recorder = nil
        startedAt = nil
        isRecording = false
        try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    }
}
