import Foundation
import Combine

/// Shared metering conversion used by both live recording and playback analysis.
enum AudioLevelNormalizer {
    static let minimumDecibels: Float = -50

    static func normalizedLevel(
        decibels: Float,
        minimumDecibels: Float = AudioLevelNormalizer.minimumDecibels
    ) -> Float {
        guard decibels.isFinite else { return 0 }
        if decibels < minimumDecibels { return 0 }
        if decibels >= 0 { return 1 }
        return min(max((decibels - minimumDecibels) / -minimumDecibels, 0), 1)
    }
}

/// The physical source selected for one recording segment.
enum RecordingSourceChoice: Identifiable, Equatable {
    case iPhone
    case spark(deviceID: String, displayName: String)

    var id: String {
        switch self {
        case .iPhone:
            return "iphone"
        case .spark(let deviceID, _):
            return "spark-\(deviceID)"
        }
    }

    var displayName: String {
        switch self {
        case .iPhone:
            return "iPhone 麦克风"
        case .spark(_, let displayName):
            return displayName
        }
    }

    var systemImage: String {
        switch self {
        case .iPhone: return "iphone"
        case .spark: return "wave.3.right.circle.fill"
        }
    }
}

enum AudioRecorderError: LocalizedError {
    case failedToStart(String)
    case failedToStop(String)

    var errorDescription: String? {
        switch self {
        case .failedToStart(let message), .failedToStop(let message):
            return message
        }
    }
}

/// Protocol abstracting audio recording capabilities.
protocol AudioRecorderProtocol: ObservableObject {
    /// Current recording state
    var isRecording: Bool { get }
    /// Elapsed recording time in seconds
    var elapsedTime: TimeInterval { get }
    /// Current amplitude level (0.0 - 1.0) for waveform visualization
    var currentAmplitude: Float { get }
    /// Rolling buffer of recent amplitude samples for waveform drawing
    var waveformSamples: [Float] { get }
    /// The local file URL of the current/last recording.
    var outputFileURL: URL? { get }
    /// Whether the active recording is paused
    var isPaused: Bool { get }
    /// User-facing name of the active recording source.
    var sourceDisplayName: String { get }
    /// Current source status, such as connecting or recording.
    var statusMessage: String { get }
    /// A recoverable error that should be shown in the recording UI.
    var errorMessage: String? { get }
    
    func startRecording()
    func stopRecording()
    func stopRecording(completion: @escaping (Result<URL?, Error>) -> Void)
    func pauseRecording()
    func resumeRecording()
}

extension AudioRecorderProtocol {
    var sourceDisplayName: String { "iPhone 麦克风" }
    var statusMessage: String { isRecording ? "正在录音" : "正在准备" }
    var errorMessage: String? { nil }

    func stopRecording(completion: @escaping (Result<URL?, Error>) -> Void) {
        stopRecording()
        completion(.success(outputFileURL))
    }
}
