namespace TeleWave.Domain.Library;

/// <summary>
/// Франшиза: упорядоченный набор шоу, который играется как одно целое. «Терминатор» — это три
/// полнометражки в порядке 1→2→3.
///
/// Живёт в библиотеке, а не в планировщике, потому что «одно произведение из трёх частей» — факт
/// о контенте, а не о канале. Планировщику коллекция видна как обычная последовательность
/// воспроизводимых единиц, ровно как сериал со своими сериями: за счёт этого «три части подряд
/// в один вечер» и «три дня по одному фильму» получаются одним и тем же слотом с разным размером
/// блока, без спецлогики для коллекций.
/// </summary>
public class Collection
{
    private readonly List<CollectionItem> _items = [];

    public Guid Id { get; private set; }
    public string Name { get; private set; } = string.Empty;
    public string? Description { get; private set; }

    /// <summary>Постер коллекции — ссылка на запись общего реестра изображений или null.</summary>
    public Guid? PosterImageId { get; private set; }

    public DateTimeOffset CreatedAt { get; private set; }

    /// <summary>Позиции коллекции (backing-field для EF); порядок показа — по <see cref="CollectionItem.Position"/>.</summary>
    public IReadOnlyList<CollectionItem> Items => _items;

    private Collection() { }

    public static Collection Create(string name, string? description = null) =>
        new()
        {
            Id = Guid.NewGuid(),
            Name = name.Trim(),
            Description = description,
            CreatedAt = DateTimeOffset.UtcNow,
        };

    public void Rename(string name, string? description)
    {
        Name = name.Trim();
        Description = description;
    }

    /// <summary>Привязать/снять постер (ссылка на реестр изображений; сама картинка остаётся в галерее).</summary>
    public void SetPosterImage(Guid? imageId) => PosterImageId = imageId;

    public bool HasShow(Guid showId) => _items.Any(i => i.ShowId == showId);

    /// <summary>Добавляет шоу в конец. Повторное добавление игнорируется — возвращает null.</summary>
    public CollectionItem? AddShow(Guid showId)
    {
        if (HasShow(showId))
            return null;

        var nextPosition = _items.Count == 0 ? 0 : _items.Max(i => i.Position) + 1;
        var item = CollectionItem.Create(Id, showId, nextPosition);
        _items.Add(item);
        return item;
    }

    public bool RemoveShow(Guid showId)
    {
        var item = _items.FirstOrDefault(i => i.ShowId == showId);
        if (item is null)
            return false;
        _items.Remove(item);
        return true;
    }

    /// <summary>
    /// Переставляет позиции в порядке переданных идентификаторов. Не упомянутые остаются после них,
    /// сохраняя относительный порядок, а неизвестные игнорируются — так частичный ввод (перетащили
    /// один элемент) не теряет остальные.
    /// </summary>
    public void Reorder(IEnumerable<Guid> showIdsInOrder)
    {
        var requested = showIdsInOrder.Distinct().Where(HasShow).ToList();
        var rest = _items
            .Where(i => !requested.Contains(i.ShowId))
            .OrderBy(i => i.Position)
            .Select(i => i.ShowId);

        var position = 0;
        foreach (var showId in requested.Concat(rest))
            _items.First(i => i.ShowId == showId).SetPosition(position++);
    }
}
