import Foundation

public enum PlaybackResolverError: Error, LocalizedError {
    case noStreams
    case invalidStreamURL
    case missingProviderPath
    case missingIdent

    public var errorDescription: String? {
        switch self {
        case .noStreams:
            return "No streams available"
        case .invalidStreamURL:
            return "Invalid stream URL"
        case .missingProviderPath:
            return "Provider stream is missing path"
        case .missingIdent:
            return "Provider response does not contain ident"
        }
    }
}

public actor PlaybackResolver {
    private let streamCinema: StreamCinemaClient
    private let kraska: KraskaClient

    public init(streamCinema: StreamCinemaClient, kraska: KraskaClient) {
        self.streamCinema = streamCinema
        self.kraska = kraska
    }

    public func listStreams(playPath: String) async throws -> [StreamOption] {
        let response = try await streamCinema.get(path: playPath)
        guard let streams = response.streams, !streams.isEmpty else {
            throw PlaybackResolverError.noStreams
        }
        return streams
    }

    public func resolve(stream: StreamOption, streamPreferences: [String: QueryValue] = [:]) async throws -> URL {
        if stream.provider?.lowercased() == "kraska" {
            guard let providerPath = stream.url else {
                throw PlaybackResolverError.missingProviderPath
            }
            let streamObject = try await streamCinema.getJSONObject(
                path: providerPath,
                params: streamPreferences
            )
            guard let ident = streamObject["ident"]?.stringValue, !ident.isEmpty else {
                throw PlaybackResolverError.missingIdent
            }
            return try await kraska.resolve(ident: ident)
        }

        guard let urlString = stream.url, let url = URL(string: urlString) else {
            throw PlaybackResolverError.invalidStreamURL
        }
        return url
    }
}
