using TeleWave.Application.Metadata;
using TeleWave.Domain.Library;

namespace TeleWave.Application.Common.Interfaces;

/// <summary>
/// Источник метаданных о шоу/сериях (TMDb, OMDb). Реализация ходит во внешний API.
///
/// Тип шоу передаётся отдельным параметром, а не зашивается в <c>externalId</c>: у TMDb сериалы и
/// фильмы нумеруются в разных пространствах, и одно и то же число там означает разное. Хранить
/// в идентификаторе синтетический префикс не пришлось — тип и так известен на месте вызова, а
/// <see cref="Show.Kind"/> неизменяем, поэтому найденный при поиске идентификатор при любом
/// последующем обращении истолкуется тем же типом.
/// </summary>
public interface IMetadataProvider
{
    /// <summary>Ключ источника: «tmdb», «omdb».</summary>
    string Key { get; }

    /// <summary>Кандидаты по названию среди контента указанного типа.</summary>
    Task<IReadOnlyList<MetadataCandidate>> SearchShowsAsync(
        string query,
        ShowKind kind,
        CancellationToken cancellationToken
    );

    /// <summary>
    /// Метаданные шоу. <paramref name="kind"/> брать из самого шоу, а не из внешнего запроса:
    /// иначе клиент может заставить записать сериалу метаданные одноимённого фильма.
    /// </summary>
    Task<ShowMetadata?> GetShowAsync(
        string externalId,
        ShowKind kind,
        CancellationToken cancellationToken
    );

    /// <summary>Метаданные серии. Только для <see cref="ShowKind.Series"/> — у остальных серий нет.</summary>
    Task<EpisodeMetadata?> GetEpisodeAsync(
        string externalId,
        int season,
        int episode,
        CancellationToken cancellationToken
    );

    /// <summary>Сколько серий в указанном сезоне по данным источника (null — сезон не найден/нет данных).</summary>
    Task<int?> GetSeasonEpisodeCountAsync(
        string externalId,
        int season,
        CancellationToken cancellationToken
    );

    /// <summary>
    /// Номера сезонов сериала по данным источника (пусто — источник не отдал данные). Спецвыпуски
    /// (нулевой сезон) не отдаются: в библиотеку они не грузятся и считались бы вечно отсутствующими.
    /// </summary>
    Task<IReadOnlyList<int>> GetSeasonNumbersAsync(
        string externalId,
        CancellationToken cancellationToken
    );
}

/// <summary>Резолвит провайдер по ключу и перечисляет реально настроенные (с API-ключом) источники.</summary>
public interface IMetadataProviderResolver
{
    IMetadataProvider? Resolve(string key);

    /// <summary>Ключи источников, у которых задан API-ключ (доступны в UI).</summary>
    IReadOnlyList<string> AvailableKeys { get; }
}
