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

namespace TeleWave.Application.Media.MovieImport;

/// <summary>
/// Один фильм к заведению. Источник файла ровно один из двух: путь в <c>manual/</c> либо уже
/// загруженный браузером ассет — грузить файл заранее имеет смысл только после того, как строку
/// подтвердили.
/// </summary>
/// <param name="Title">Название на случай, если кандидат не выбран: шоу всё равно надо как-то назвать.</param>
/// <param name="ExternalId">Кандидат источника; null — завести шоу без метаданных.</param>
public sealed record MovieImportItem(
    string? RelativePath,
    Guid? AssetId,
    string Title,
    int? Year,
    string? ExternalId
);

public sealed record ImportMoviesCommand(IReadOnlyList<MovieImportItem> Items, string Provider)
    : ICommand<Result<ImportMoviesResultDto>>;

/// <param name="Created">Сколько шоу заведено.</param>
/// <param name="Enriched">Скольким из них применены метаданные источника.</param>
/// <param name="Failed">Что не получилось — по строке на фильм, а не одной ошибкой на всё.</param>
public sealed record ImportMoviesResultDto(
    int Created,
    int Enriched,
    IReadOnlyList<MovieImportFailureDto> Failed
);

public sealed record MovieImportFailureDto(string Title, string Reason);

public sealed class ImportMoviesCommandValidator : AbstractValidator<ImportMoviesCommand>
{
    public ImportMoviesCommandValidator()
    {
        RuleFor(x => x.Items).NotEmpty();
        RuleFor(x => x.Items.Count).LessThanOrEqualTo(200);
        RuleFor(x => x.Provider).NotEmpty();

        RuleForEach(x => x.Items)
            .ChildRules(item =>
            {
                item.RuleFor(i => i.Title).NotEmpty().MaximumLength(256);
                item.RuleFor(i => i.Year)
                    .InclusiveBetween(1870, 2200)
                    .When(i => i.Year is not null);
                // Ровно один источник файла: без файла шоу пустое, с двумя неясно, какой брать.
                item.RuleFor(i => i)
                    .Must(i => string.IsNullOrWhiteSpace(i.RelativePath) != (i.AssetId is null))
                    .WithMessage("У фильма должен быть ровно один источник файла.");
            });
    }
}
