import Foundation
import SwiftData

/// A playlist — an ordered collection of tracks for building a mix.
@Model
final class Playlist {
    var id: UUID
    var name: String
    var notes: String
    var dateCreated: Date
    var dateModified: Date
    var targetBPM: Double?             // target BPM for the mix
    var color: String                  // hex color for UI

    /// Template for grouping tracks in the playlist view.
    /// Uses {Artist}, {Album}, {Genre}, {Year}, {Folder} placeholders.
    /// Example: "{Album} ({Year})" → "Only Built 4 Cuban Linx (1995)"
    /// Empty string = no grouping.
    var groupTemplate: String

    @Relationship(deleteRule: .cascade, inverse: \PlaylistEntry.playlist)
    var entries: [PlaylistEntry]

    /// The folder this playlist belongs to (nil = top level).
    var folder: PlaylistFolder?

    /// Entries sorted by position.
    var sortedEntries: [PlaylistEntry] {
        entries.sorted { $0.position < $1.position }
    }

    var totalDuration: TimeInterval {
        // Sum duration from entries that have valid tracks
        // Note: avoid KeyPath traversal (.track?.duration) which crashes on invalidated SwiftData models
        var total: TimeInterval = 0
        for entry in entries {
            guard let track = entry.track else { continue }
            total += track.duration
        }
        return total
    }

    var formattedTotalDuration: String {
        let total = Int(totalDuration)
        let hours = total / 3600
        let minutes = (total % 3600) / 60
        let seconds = total % 60
        if hours > 0 {
            return String(format: "%d:%02d:%02d", hours, minutes, seconds)
        }
        return String(format: "%d:%02d", minutes, seconds)
    }

    var trackCount: Int { entries.count }

    init(
        name: String,
        notes: String = "",
        color: String = "#2196F3"
    ) {
        self.id = UUID()
        self.name = name
        self.notes = notes
        self.dateCreated = Date()
        self.dateModified = Date()
        self.targetBPM = nil
        self.color = color
        self.groupTemplate = ""
        self.entries = []
    }

    func addTrack(_ track: Track, crossfadeDuration: TimeInterval = 0) {
        let position = entries.count
        let entry = PlaylistEntry(
            position: position,
            track: track,
            crossfadeDuration: crossfadeDuration
        )
        entries.append(entry)
        dateModified = Date()
    }

    func removeEntry(at position: Int) {
        entries.removeAll { $0.position == position }
        for (index, entry) in sortedEntries.enumerated() {
            entry.position = index
        }
        dateModified = Date()
    }

    func moveEntry(from source: Int, to destination: Int) {
        var sorted = sortedEntries
        let entry = sorted.remove(at: source)
        sorted.insert(entry, at: destination)
        for (index, e) in sorted.enumerated() {
            e.position = index
        }
        dateModified = Date()
    }
}

/// A single entry in a playlist, linking a track with transition info.
@Model
final class PlaylistEntry {
    var id: UUID
    var position: Int
    var track: Track?

    // Transition settings
    var crossfadeDuration: TimeInterval    // seconds of overlap with next track
    var startOffset: TimeInterval          // start playback from this point
    var endOffset: TimeInterval            // stop playback at this point (0 = end of track)
    var gainAdjustment: Double             // dB adjustment (-12 to +12)
    var notes: String

    var playlist: Playlist?

    /// Effective duration considering start/end offsets.
    var effectiveDuration: TimeInterval {
        guard let track else { return 0 }
        let end = endOffset > 0 ? endOffset : track.duration
        return max(0, end - startOffset)
    }

    init(
        position: Int,
        track: Track?,
        crossfadeDuration: TimeInterval = 0,
        startOffset: TimeInterval = 0,
        endOffset: TimeInterval = 0,
        gainAdjustment: Double = 0,
        notes: String = ""
    ) {
        self.id = UUID()
        self.position = position
        self.track = track
        self.crossfadeDuration = crossfadeDuration
        self.startOffset = startOffset
        self.endOffset = endOffset
        self.gainAdjustment = gainAdjustment
        self.notes = notes
    }
}
