using FluentValidation;
using LiteCqrs;
using TeleWave.Application.Common.Models;
using TeleWave.Domain.Broadcast;

namespace TeleWave.Application.Broadcast.Bumpers;

public sealed record ListBumperTemplatesQuery : IQuery<IReadOnlyList<BumperTemplateDto>>;

public sealed record CreateBumperTemplateCommand(string Name) : ICommand<Result<Guid>>;

/// <summary>Оформление блока: имя, шрифт и палитра. Меняет ревизию — заставки пересобираются.</summary>
public sealed record UpdateBumperTemplateCommand(Guid TemplateId, BumperStyle Style)
    : ICommand<Result>;

public sealed record DeleteBumperTemplateCommand(Guid TemplateId) : ICommand<Result>;

public sealed record SetBumperTemplateAudioCommand(
    Guid TemplateId,
    string Extension,
    double DurationSeconds
) : ICommand<Result>;

public sealed record ClearBumperTemplateAudioCommand(Guid TemplateId) : ICommand<Result>;

public sealed record SetBumperTemplateBackgroundCommand(Guid TemplateId, Guid ImageId)
    : ICommand<Result>;

public sealed record ClearBumperTemplateBackgroundCommand(Guid TemplateId) : ICommand<Result>;

public sealed record AddBumperVariantCommand(Guid TemplateId, string Name) : ICommand<Result<Guid>>;

/// <summary>Полное содержимое подблока — строки редактор всегда присылает списком целиком.</summary>
public sealed record BumperVariantInput(
    string Name,
    BumperTrigger Trigger,
    BumperBackground Background,
    int Weight,
    IReadOnlyList<BumperLineDto> Lines,
    /// <summary>Ролик-подложка для фона <see cref="BumperBackground.Clip"/>.</summary>
    Guid? BackgroundClipShowId = null
);

public sealed record UpdateBumperVariantCommand(
    Guid TemplateId,
    Guid VariantId,
    BumperVariantInput Input
) : ICommand<Result>;

public sealed record RemoveBumperVariantCommand(Guid TemplateId, Guid VariantId) : ICommand<Result>;

/// <summary>
/// Рендер примера заставки. Канал нужен только для образцов подстановки: блок общий, но посмотреть
/// его надо глазами конкретного канала — иначе <c>{channel}</c> не на что заменить.
/// </summary>
public sealed record RenderBumperPreviewCommand(Guid TemplateId, Guid? ChannelId)
    : ICommand<Result>;

public sealed class CreateBumperTemplateCommandValidator
    : AbstractValidator<CreateBumperTemplateCommand>
{
    public CreateBumperTemplateCommandValidator() =>
        RuleFor(x => x.Name).NotEmpty().MaximumLength(64);
}

public sealed class UpdateBumperTemplateCommandValidator
    : AbstractValidator<UpdateBumperTemplateCommand>
{
    public UpdateBumperTemplateCommandValidator()
    {
        RuleFor(x => x.Style.Name).NotEmpty().MaximumLength(64);
        RuleFor(x => x.Style.BackgroundColor).NotEmpty().MaximumLength(32);
        RuleFor(x => x.Style.BackgroundColor2).NotEmpty().MaximumLength(32);
        RuleFor(x => x.Style.AccentColor).NotEmpty().MaximumLength(32);
        RuleFor(x => x.Style.TextColor).NotEmpty().MaximumLength(32);
    }
}

public sealed class AddBumperVariantCommandValidator : AbstractValidator<AddBumperVariantCommand>
{
    public AddBumperVariantCommandValidator() => RuleFor(x => x.Name).NotEmpty().MaximumLength(64);
}

public sealed class UpdateBumperVariantCommandValidator
    : AbstractValidator<UpdateBumperVariantCommand>
{
    /// <summary>Больше шести строк в кадр не помещается ни при каком размере шрифта.</summary>
    private const int MaxLines = 6;

    public UpdateBumperVariantCommandValidator()
    {
        RuleFor(x => x.Input.Name).NotEmpty().MaximumLength(64);
        RuleFor(x => x.Input.Weight).InclusiveBetween(0, 1000);
        RuleFor(x => x.Input.Lines).NotNull().Must(l => l.Count <= MaxLines);
        RuleForEach(x => x.Input.Lines)
            .ChildRules(line => line.RuleFor(l => l.Text).NotEmpty().MaximumLength(120));

        // Фон из ролика без самого ролика — это не «пока не выбрал», а заставка, которая молча
        // отрендерится градиентом. Пусть выбор будет обязательным сразу.
        RuleFor(x => x.Input.BackgroundClipShowId)
            .NotNull()
            .When(x => x.Input.Background == BumperBackground.Clip);
    }
}
