import Foundation

struct Chapter: Codable, Identifiable, Hashable {
    let id: Int
    let start: Double
    let end: Double
    let title: String
}

struct Library: Codable, Identifiable, Hashable {
    let id: String
    let name: String
    let mediaType: String?
}

/// Wichtig für `ForEach`: Synthetische Podcast-Episoden-Items (z.B. aus der
/// library-weiten Folgensuche) teilen sich denselben `id` (Podcast-Container-ID)
/// und unterscheiden sich nur über `episodeId`. Default-`Identifiable` würde
/// hier kollidieren. **Immer** `ForEach(items, id: \.syncKey)` benutzen wenn
/// die Liste sowohl Container als auch Episoden-Items enthalten kann.
struct LibraryItem: Codable, Identifiable, Hashable {
    let id: String
    let title: String
    let author: String
    let durationSeconds: Double
    let audioFiles: [AudioFile]
    var mediaType: String = "book"
    var episodeId: String? = nil
    var description: String? = nil
    var chapters: [Chapter] = []

    var isPodcast: Bool { mediaType == "podcast" }
    var isPodcastContainer: Bool { isPodcast && episodeId == nil }
    var isPodcastEpisode: Bool { isPodcast && episodeId != nil }

    static func == (lhs: LibraryItem, rhs: LibraryItem) -> Bool {
        lhs.id == rhs.id && lhs.episodeId == rhs.episodeId
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(episodeId)
    }
}

struct PodcastEpisode: Identifiable, Hashable, Codable {
    let id: String
    let title: String
    let pubDate: String?
    let publishedAtMillis: Double?
    let season: String?
    let episode: String?
    let durationSeconds: Double
    let audioFile: AudioFile

    var formattedDate: String? {
        if let ms = publishedAtMillis, ms > 0 {
            let date = Date(timeIntervalSince1970: ms / 1000.0)
            let df = DateFormatter()
            df.dateStyle = .medium
            df.timeStyle = .none
            return df.string(from: date)
        }
        return pubDate
    }
}

struct AudioFile: Codable, Hashable {
    let ino: String
    let filename: String
    let ext: String
    let durationSeconds: Double
    let index: Int
}

struct PlaybackProgress: Codable, Hashable {
    let itemId: String
    var episodeId: String?
    var currentTime: Double
    var duration: Double
    var isFinished: Bool
    var updatedAt: Date
    /// Server-assigned UUID for this progress entry. Required to delete it —
    /// Audiobookshelf's `DELETE /api/me/progress/:id` matches by this id, NOT
    /// by libraryItemId. Optional so older persisted caches still decode.
    var id: String?

    var syncKey: String {
        if let episodeId { return "\(itemId)|\(episodeId)" }
        return itemId
    }
}

enum DownloadState: Equatable {
    case notDownloaded
    case downloading(progress: Double)
    case downloaded
    case failed(message: String)
}
