import AVFoundation
import Defaults
import Foundation

struct PlayerQueueItem: Hashable, Identifiable, Defaults.Serializable {
    static let bridge = PlayerQueueItemBridge()

    var id = UUID()
    var video: Video!
    var videoID: Video.ID
    var app: VideosApp?
    var instanceURL: URL?
    var playbackTime: CMTime?
    var videoDuration: TimeInterval?

    static func from(_ watch: Watch, video: Video? = nil) -> Self {
        .init(
            video,
            videoID: watch.videoID,
            app: watch.app,
            instanceURL: watch.instanceURL,
            playbackTime: CMTime.secondsInDefaultTimescale(watch.stoppedAt),
            videoDuration: watch.videoDuration
        )
    }

    init(
        _ video: Video? = .fixture,
        videoID: Video.ID? = nil,
        app: VideosApp? = nil,
        instanceURL: URL? = nil,
        playbackTime: CMTime? = nil,
        videoDuration: TimeInterval? = nil
    ) {
        self.video = video
        self.videoID = videoID ?? video!.videoID
        self.app = app
        self.instanceURL = instanceURL
        self.playbackTime = playbackTime
        self.videoDuration = videoDuration
    }

    var duration: TimeInterval {
        videoDuration ?? video?.length ?? .zero
    }

    var shouldRestartPlaying: Bool {
        guard Defaults[.watchedVideoPlayNowBehavior] == .continue else { return true }

        guard let seconds = playbackTime?.seconds else {
            return false
        }

        if duration <= 0 {
            return false
        }

        return (seconds / duration) * 100 > Double(Defaults[.watchedThreshold])
    }

    var hasDetailsLoaded: Bool {
        guard let video else { return false }
        return !video.streams.isEmpty
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }

    var contentItem: ContentItem {
        .init(video: contentItemVideo)
    }

    var contentItemVideo: Video {
        video ?? Video(app: app ?? .invidious, instanceURL: instanceURL, videoID: videoID, length: videoDuration ?? 0)
    }
}
