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

namespace TeleWave.Application.Programming.Templates.Layers;

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

public sealed record UpdateLayerCommand(
    Guid LayerId,
    string Name,
    int Priority,
    LayerApplicability? Applicability,
    bool IsEnabled
) : ICommand<Result>;

public sealed record DeleteLayerCommand(Guid LayerId) : ICommand<Result>;

/// <summary>Имя шаблона, аварийная группа, стык по умолчанию и правила отбора кандидатов.</summary>
public sealed record UpdateTemplateCommand(
    Guid TemplateId,
    string Name,
    Guid? FallbackGroupId,
    Guid? DefaultJunctionId,
    PlanningRules? Rules
) : ICommand<Result>;

public sealed class CreateLayerCommandValidator : AbstractValidator<CreateLayerCommand>
{
    public CreateLayerCommandValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(128);
        RuleFor(x => x.Priority).InclusiveBetween(1, 1000);
    }
}

public sealed class UpdateLayerCommandValidator : AbstractValidator<UpdateLayerCommand>
{
    public UpdateLayerCommandValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(128);
        RuleFor(x => x.Priority).InclusiveBetween(1, 1000);
    }
}

public sealed class UpdateTemplateCommandValidator : AbstractValidator<UpdateTemplateCommand>
{
    public UpdateTemplateCommandValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(256);

        // Год — верхняя граница окна повторов: за ним правило перестаёт что-либо значить, а история
        // всё равно ограничена глубиной хранения ленты.
        RuleFor(x => x.Rules!.MaxRepeatsInWindow!.WindowDays)
            .InclusiveBetween(1, 365)
            .When(x => x.Rules?.MaxRepeatsInWindow is not null);
        RuleFor(x => x.Rules!.MaxRepeatsInWindow!.Max)
            .InclusiveBetween(1, 1000)
            .When(x => x.Rules?.MaxRepeatsInWindow is not null);

        RuleForEach(x => x.Rules!.MaxAudienceByTime)
            .Must(window => window.From != window.To)
            .WithMessage("Окно нулевой длины ничего не ограничивает.")
            .When(x => x.Rules?.MaxAudienceByTime is not null);
    }
}
