#if canImport(AppKit)
    import AppKit
#endif
import Foundation
import Logging
#if canImport(UIKit)
    import UIKit
#endif
import SwiftUI

struct OpenVideosModel {
    enum PlaybackMode: String, CaseIterable {
        case playNow
        case shuffleAll
        case playNext
        case playLast

        var description: String {
            switch self {
            case .playNow:
                return "Play Now".localized()
            case .shuffleAll:
                return "Shuffle All".localized()
            case .playNext:
                return "Play Next".localized()
            case .playLast:
                return "Play Last".localized()
            }
        }

        var allowsRemovingQueueItems: Bool {
            self == .playNow || self == .shuffleAll
        }

        var allowedWhenQueueIsEmpty: Bool {
            self == .playNow || self == .shuffleAll
        }
    }

    static let shared = Self()
    var player: PlayerModel! = .shared
    var logger = Logger(label: "stream.yattee.open-videos")

    func open(_ url: URL) {
        if url.startAccessingSecurityScopedResource() {
            let video = Video.local(url)

            player.play([video], shuffling: false)
        }
    }

    var urlsFromClipboard: [URL] {
        #if os(iOS)
            if let pasteboard = UIPasteboard.general.urls {
                return pasteboard
            }
        #elseif os(macOS)
            if let pasteboard = NSPasteboard.general.string(forType: .string) {
                return urlsFrom(pasteboard)
            }
        #endif

        return []
    }

    func openURLsFromClipboard(removeQueueItems: Bool = false, playbackMode: Self.PlaybackMode = .playNow) {
        if urlsFromClipboard.isEmpty {
            NavigationModel.shared.alert = Alert(title: Text("Could not find any links to open in your clipboard".localized()))
            if NavigationModel.shared.presentingOpenVideos {
                NavigationModel.shared.presentingAlertInOpenVideos = true
            } else {
                NavigationModel.shared.presentingAlert = true
            }
        } else {
            openURLs(urlsFromClipboard, removeQueueItems: removeQueueItems, playbackMode: playbackMode)
        }
    }

    func openURLs(_ urls: [URL], removeQueueItems: Bool = false, playbackMode: Self.PlaybackMode = .playNow) {
        guard !urls.isEmpty else {
            return
        }

        NavigationModel.shared.presentingOpenVideos = false

        logger.info("opening \(urls.count) urls")
        urls.forEach { logger.info("\($0.absoluteString)") }

        if removeQueueItems, playbackMode.allowsRemovingQueueItems {
            player.removeQueueItems()
            logger.info("removing queue items")
        }

        switch playbackMode {
        case .playNow:
            player.playbackMode = .queue
        case .shuffleAll:
            player.playbackMode = .shuffle
        case .playNext:
            player.playbackMode = .queue
        case .playLast:
            player.playbackMode = .queue
        }

        enqueue(
            urls,
            prepending: playbackMode == .playNow || playbackMode == .playNext
        )

        NavigationModel.shared.presentingChannelSheet = false

        if playbackMode == .playNow || playbackMode == .shuffleAll {
            #if os(iOS)
                if player.presentingPlayer {
                    player.advanceToNextItem()
                } else {
                    player.onPresentPlayer.append { [weak player] in player?.advanceToNextItem() }
                }
            #else
                player.advanceToNextItem()
            #endif
            player.show()
        }
    }

    func enqueue(_ urls: [URL], prepending: Bool = false) {
        var videos = urls.compactMap { url in
            var video: Video!
            if canOpenVideosByID {
                let parser = URLParser(url: url)

                if parser.destination == .video, let id = parser.videoID {
                    video = Video(app: .local, videoID: id)
                    logger.info("identified remote video: \(id)")
                } else {
                    video = .local(url)
                    logger.info("identified local video: \(url.absoluteString)")
                }
            } else {
                video = .local(url)
                logger.info("identified local video: \(url.absoluteString)")
            }

            return video
        }

        if prepending {
            videos.reverse()
        }
        for video in videos {
            player.enqueueVideo(video, play: false, prepending: prepending, loadDetails: false)
        }
    }

    func urlsFrom(_ string: String) -> [URL] {
        string.split(whereSeparator: \.isNewline).compactMap { URL(string: String($0)) }
    }

    var canOpenVideosByID: Bool {
        guard let app = AccountsModel.shared.current?.app else { return false }
        return !AccountsModel.shared.isEmpty && app.supportsOpeningVideosByID
    }
}