using TeleWave.Domain.Library;

namespace TeleWave.Application.Metadata;

/// <summary>
/// Приведение возрастного рейтинга из внешнего источника к шкале <see cref="ShowAudience"/>.
///
/// Живёт в приложении, а не в провайдере: таблица соответствий одна на все источники, и разъехавшись
/// по провайдерам она бы означала, что одно и то же шоу получает разный рейтинг в зависимости от того,
/// откуда его подтянули.
///
/// Незнакомое значение — <c>null</c>, а не догадка. Источники наряду с рейтингами отдают
/// «Not Rated», «Approved», «Passed», «N/A» и шкалы, которых здесь нет; проставить по ним
/// хоть что-то значит поставить в детский эфир непроверенное.
///
/// Таблица плоская — без указания страны, — и это работает, пока написания не сталкиваются: у нас
/// это US (<c>PG-13</c>, <c>TV-14</c>) и RU (<c>12+</c>). Появится третья страна — столкновение
/// почти наверняка будет: Германия и Франция используют голые <c>12</c>/<c>16</c>/<c>18</c>,
/// означающие разное. Тогда <see cref="Parse"/> придётся сделать country-aware, а не дописывать
/// в таблицу ещё строк.
/// </summary>
public static class ContentRating
{
    private static readonly Dictionary<string, ShowAudience> Known = new(
        StringComparer.OrdinalIgnoreCase
    )
    {
        // ── MPAA (полный метр) ──
        ["G"] = ShowAudience.G,
        ["PG"] = ShowAudience.Pg,
        ["PG-13"] = ShowAudience.Pg13,
        ["R"] = ShowAudience.R,
        ["NC-17"] = ShowAudience.Nc17,

        // ── TV Parental Guidelines (сериалы). Отдельной шкалой в домене не заводим — по замыслу
        //    рейтинг один, — поэтому приводим к ближайшему по строгости. ──
        ["TV-Y"] = ShowAudience.G,
        ["TV-Y7"] = ShowAudience.G,
        ["TV-Y7-FV"] = ShowAudience.G,
        ["TV-G"] = ShowAudience.G,
        ["TV-PG"] = ShowAudience.Pg,
        ["TV-14"] = ShowAudience.Pg13,
        ["TV-MA"] = ShowAudience.R,

        // ── Исторические обозначения MPAA: в старом кино IMDb отдаёт именно их. «M» и «GP»
        //    впоследствии стали «PG», «X» — «NC-17». ──
        ["M"] = ShowAudience.Pg,
        ["M/PG"] = ShowAudience.Pg,
        ["GP"] = ShowAudience.Pg,
        ["X"] = ShowAudience.Nc17,
        ["AO"] = ShowAudience.Nc17,

        // ── Российская возрастная маркировка (TMDb отдаёт её для RU). Это не перевод, а сближение
        //    по смыслу: шкалы построены по-разному, точного соответствия между ними нет.
        //    18+ приведён к R, а не к NC-17: в России 18+ носит рядовой боевик, тогда как NC-17 —
        //    редкость, и свалив туда всё 18+ мы обессмыслили бы верх шкалы. ──
        ["0+"] = ShowAudience.G,
        ["6+"] = ShowAudience.G,
        ["12+"] = ShowAudience.Pg,
        ["16+"] = ShowAudience.Pg13,
        ["18+"] = ShowAudience.R,
    };

    /// <summary>Рейтинг по написанию источника; null — значение отсутствует либо не распознано.</summary>
    public static ShowAudience? Parse(string? value) =>
        !string.IsNullOrWhiteSpace(value) && Known.TryGetValue(value.Trim(), out var audience)
            ? audience
            : null;
}
