namespace TeleWave.Domain.Library;

/// <summary>
/// Жанр из общего справочника. Справочник, а не свободные строки: по нему собираются группы контента
/// для планировщика («один случайный боевик по пятницам»), а жанры от внешних провайдеров
/// (TMDb/OMDb) приводятся к нему через <see cref="Aliases"/>.
///
/// Свои произвольные метки («ретро», «новогоднее») сюда не заводятся — их роль выполняют группы
/// с ручным составом.
/// </summary>
public class Genre
{
    private readonly List<GenreAlias> _aliases = [];

    public Guid Id { get; private set; }

    /// <summary>Отображаемое название («Боевик»).</summary>
    public string Name { get; private set; } = string.Empty;

    /// <summary>Стабильный ключ («action») — по нему жанр находится при повторном сидинге.</summary>
    public string Slug { get; private set; } = string.Empty;

    /// <summary>Порядок в списках UI (меньше — выше).</summary>
    public int SortOrder { get; private set; }

    /// <summary>Признак жанра из стартового сида — такой нельзя удалить, только переименовать.</summary>
    public bool IsSystem { get; private set; }

    public DateTimeOffset CreatedAt { get; private set; }

    /// <summary>Варианты написания для сопоставления с внешними источниками (backing-field для EF).</summary>
    public IReadOnlyList<GenreAlias> Aliases => _aliases;

    private Genre() { }

    public static Genre Create(
        string name,
        string slug,
        int sortOrder = 0,
        bool isSystem = false
    ) =>
        new()
        {
            Id = Guid.NewGuid(),
            Name = name.Trim(),
            Slug = GenreAlias.Normalize(slug),
            SortOrder = sortOrder,
            IsSystem = isSystem,
            CreatedAt = DateTimeOffset.UtcNow,
        };

    public void Rename(string name) => Name = name.Trim();

    public void SetSortOrder(int sortOrder) => SortOrder = sortOrder;

    /// <summary>Добавляет вариант написания, если такого ещё нет. Пустые значения игнорируются.</summary>
    public void AddAlias(string alias)
    {
        var normalized = GenreAlias.Normalize(alias);
        if (normalized.Length == 0 || _aliases.Any(a => a.Value == normalized))
            return;
        _aliases.Add(GenreAlias.Create(Id, normalized));
    }

    /// <summary>
    /// Полностью заменяет набор вариантов написания. Снятые псевдонимы из сида вернутся при следующем
    /// старте приложения — сид дописывает недостающие, но только если их не занял другой жанр.
    /// </summary>
    public void ReplaceAliases(IEnumerable<string> aliases)
    {
        _aliases.Clear();
        foreach (var alias in aliases)
            AddAlias(alias);
    }
}
