namespace TeleWave.Domain.Programming;

/// <summary>Что за врезка стоит в стыке.</summary>
public enum JunctionElementKind
{
    /// <summary>Реклама — ролики или готовые рекламные блоки из группы.</summary>
    Ad = 0,

    /// <summary>Анонс: «смотрите в четверг».</summary>
    Promo = 1,

    /// <summary>ТВ-заставка «Сейчас — Далее»: ассет рендерится под конкретную пару шоу.</summary>
    Bumper = 2,

    /// <summary>Заполнитель: закрывает остаток, когда врезки не добрали до цели.</summary>
    Filler = 3,
}

/// <summary>Чем меряется врезка.</summary>
public enum JunctionAmountMode
{
    /// <summary>Ровно N единиц. Предсказуемо по числу, но не по времени.</summary>
    Count = 0,

    /// <summary>
    /// Пока не наберётся M минут. Нужен для смешанных групп, где рядом лежат и целые рекламные
    /// блоки, и отдельные ролики: «одна единица» там означает то ли 20 секунд, то ли три минуты.
    /// </summary>
    Duration = 1,
}

/// <summary>
/// Врезка в шаблоне стыка. Условия показа хранятся структурно (<see cref="ConditionsJson"/>),
/// а не выражением: парсер, его валидация и отдельный UI обошлись бы дорого, а покрывают ровно
/// те же три-четыре реальных случая.
/// </summary>
public class JunctionElement
{
    public Guid Id { get; private set; }
    public Guid JunctionTemplateId { get; private set; }
    public int Position { get; private set; }
    public JunctionElementKind Kind { get; private set; }

    /// <summary>Откуда брать единицы — для <see cref="JunctionElementKind.Ad"/>, <see cref="JunctionElementKind.Promo"/>, <see cref="JunctionElementKind.Filler"/>.</summary>
    public Guid? GroupId { get; private set; }

    /// <summary>Какой блок заставки рендерить — для <see cref="JunctionElementKind.Bumper"/>.</summary>
    public Guid? BumperTemplateId { get; private set; }

    public JunctionAmountMode AmountMode { get; private set; }

    /// <summary>Единиц либо минут.</summary>
    public int AmountValue { get; private set; }

    /// <summary>Обязательную врезку нельзя выбросить при нехватке времени.</summary>
    public bool IsRequired { get; private set; }

    /// <summary>Условия показа (JSON). Домен их не интерпретирует — схема живёт в Application.</summary>
    public string? ConditionsJson { get; private set; }

    private JunctionElement() { }

    internal static JunctionElement Create(
        Guid junctionTemplateId,
        int position,
        JunctionElementKind kind
    ) =>
        new()
        {
            Id = Guid.NewGuid(),
            JunctionTemplateId = junctionTemplateId,
            Position = position,
            Kind = kind,
            AmountMode = JunctionAmountMode.Count,
            AmountValue = 1,
            IsRequired = false,
        };

    public void Update(
        JunctionElementKind kind,
        Guid? groupId,
        Guid? bumperTemplateId,
        JunctionAmountMode amountMode,
        int amountValue,
        bool isRequired,
        string? conditionsJson
    )
    {
        Kind = kind;
        AmountMode = amountMode;
        AmountValue = Math.Max(1, amountValue);
        IsRequired = isRequired;
        ConditionsJson = string.IsNullOrWhiteSpace(conditionsJson) ? null : conditionsJson;

        // Источник зависит от типа врезки: у заставки нет группы, у остальных нет блока заставки.
        // Оставленная от прежнего типа ссылка потом читалась бы генератором как настройка.
        GroupId = kind == JunctionElementKind.Bumper ? null : groupId;
        BumperTemplateId = kind == JunctionElementKind.Bumper ? bumperTemplateId : null;
    }

    internal void SetPosition(int position) => Position = position;
}
