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

namespace TeleWave.Application.Programming.Templates.Junctions;

public sealed record ListJunctionsQuery(Guid ChannelId)
    : IQuery<IReadOnlyList<JunctionTemplateDto>>;

public sealed record CreateJunctionCommand(Guid ChannelId, string Name) : ICommand<Result<Guid>>;

public sealed record RenameJunctionCommand(Guid JunctionId, string Name) : ICommand<Result>;

public sealed record DeleteJunctionCommand(Guid JunctionId) : ICommand<Result>;

public sealed record AddJunctionElementCommand(Guid JunctionId, JunctionElementKind Kind)
    : ICommand<Result<Guid>>;

/// <summary>Полный набор настроек врезки — то же тело для правки любого элемента стыка.</summary>
public sealed record JunctionElementInput(
    JunctionElementKind Kind,
    Guid? GroupId,
    Guid? BumperTemplateId,
    JunctionAmountMode AmountMode,
    int AmountValue,
    bool IsRequired,
    JunctionConditions? Conditions
);

public sealed record UpdateJunctionElementCommand(
    Guid JunctionId,
    Guid ElementId,
    JunctionElementInput Input
) : ICommand<Result>;

public sealed record RemoveJunctionElementCommand(Guid JunctionId, Guid ElementId)
    : ICommand<Result>;

public sealed record ReorderJunctionCommand(Guid JunctionId, IReadOnlyList<Guid> ElementIdsInOrder)
    : ICommand<Result>;

public sealed class CreateJunctionCommandValidator : AbstractValidator<CreateJunctionCommand>
{
    public CreateJunctionCommandValidator() => RuleFor(x => x.Name).NotEmpty().MaximumLength(128);
}

public sealed class RenameJunctionCommandValidator : AbstractValidator<RenameJunctionCommand>
{
    public RenameJunctionCommandValidator() => RuleFor(x => x.Name).NotEmpty().MaximumLength(128);
}

public sealed class UpdateJunctionElementCommandValidator
    : AbstractValidator<UpdateJunctionElementCommand>
{
    public UpdateJunctionElementCommandValidator()
    {
        // Верхняя граница — сутки: врезка длиннее вещательного дня бессмысленна.
        RuleFor(x => x.Input.AmountValue).InclusiveBetween(1, 24 * 60);
        RuleFor(x => x.Input.Conditions!.MinMinutesBetween)
            .InclusiveBetween(0, 24 * 60)
            .When(x => x.Input.Conditions is not null);
    }
}
