import Foundation
import SwiftData

/// Represents a single audio track in the library.
@Model
final class Track {
    var id: UUID
    var title: String
    var artist: String
    var album: String
    var genre: String

    /// Path relative to the app's documents directory (e.g. "Music/Artist - Title.mp3").
    var filePath: String

    /// Original filename without directory (used for cross-device matching).
    var fileName: String

    var duration: TimeInterval
    var bpm: Double?
    var musicalKey: String?
    var sampleRate: Double
    var bitDepth: Int
    var channels: Int
    var fileFormat: String
    var fileSizeBytes: Int64
    var year: Int?                 // release year from metadata
    var dateAdded: Date
    var lastPlayed: Date?
    var playCount: Int
    var rating: Int       // 0-5 stars
    var color: String?    // user-assigned color tag
    var notes: String

    // MARK: - Cloud (Chad Music) fields

    /// If true, this track is from Chad Music cloud — streamed via AVPlayer, not local file.
    var isCloud: Bool = false

    /// Chad Music server URL for streaming (e.g., "/music/Artist/Album/track.mp3").
    var cloudStreamPath: String?

    /// Chad Music track ID (hex string from server).
    var cloudTrackId: String?

    /// Cached waveform samples (downsampled min/max pairs), stored as Data for efficiency.
    var waveformData: Data?

    /// Whether BPM/key analysis has been performed.
    var isAnalyzed: Bool

    @Relationship(deleteRule: .cascade, inverse: \CuePoint.track)
    var cuePoints: [CuePoint]

    /// Resolve the full file URL from the app's documents directory.
    var fileURL: URL {
        let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        return docs.appendingPathComponent(filePath).standardizedFileURL
    }

    /// True if this track has a valid local file (not a cloud-only track).
    var hasLocalFile: Bool {
        !filePath.isEmpty && !isCloud
    }

    var formattedDuration: String {
        let minutes = Int(duration) / 60
        let seconds = Int(duration) % 60
        return String(format: "%d:%02d", minutes, seconds)
    }

    var formattedBPM: String {
        guard let bpm else { return "—" }
        return String(format: "%.1f", bpm)
    }

    var formattedFileSize: String {
        ByteCountFormatter.string(fromByteCount: fileSizeBytes, countStyle: .file)
    }

    init(
        title: String,
        artist: String = "",
        album: String = "",
        genre: String = "",
        filePath: String,
        fileName: String = "",
        duration: TimeInterval = 0,
        sampleRate: Double = 44100,
        bitDepth: Int = 16,
        channels: Int = 2,
        fileFormat: String = "",
        fileSizeBytes: Int64 = 0
    ) {
        self.id = UUID()
        self.title = title
        self.artist = artist
        self.album = album
        self.genre = genre
        self.filePath = filePath
        self.fileName = fileName.isEmpty ? (filePath as NSString).lastPathComponent : fileName
        self.duration = duration
        self.bpm = nil
        self.musicalKey = nil
        self.sampleRate = sampleRate
        self.bitDepth = bitDepth
        self.channels = channels
        self.fileFormat = fileFormat
        self.fileSizeBytes = fileSizeBytes
        self.year = nil
        self.dateAdded = Date()
        self.lastPlayed = nil
        self.playCount = 0
        self.rating = 0
        self.color = nil
        self.notes = ""
        self.waveformData = nil
        self.isAnalyzed = false
        self.isCloud = false
        self.cloudStreamPath = nil
        self.cloudTrackId = nil
        self.cuePoints = []
    }

    /// Create a Track from a Chad Music cloud track.
    static func fromCloud(_ chadTrack: ChadTrack) -> Track {
        let track = Track(
            title: chadTrack.title,
            artist: chadTrack.artist ?? "",
            album: chadTrack.album ?? "",
            filePath: "",
            duration: chadTrack.duration ?? 0
        )
        track.isCloud = true
        track.cloudStreamPath = chadTrack.url
        track.cloudTrackId = chadTrack.id
        track.year = chadTrack.year
        return track
    }
}
