using FluentAssertions;
using FluentValidation.TestHelper;
using SIGCM2.Application.ProductTypes.Create;
using SIGCM2.Application.ProductTypes.Update;

namespace SIGCM2.Application.Tests.ProductTypes.Validators;

public class ProductTypeValidatorsTests
{
    private readonly CreateProductTypeCommandValidator _createValidator = new();
    private readonly UpdateProductTypeCommandValidator _updateValidator = new();

    // ── Create: Nombre validations ────────────────────────────────────────────

    [Fact]
    public void Create_NombreEmpty_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { Nombre = "" };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.Nombre);
    }

    [Fact]
    public void Create_NombreWhitespace_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { Nombre = "   " };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.Nombre);
    }

    [Fact]
    public void Create_NombreOver200Chars_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { Nombre = new string('A', 201) };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.Nombre);
    }

    // ── Create: MaxImages validations ─────────────────────────────────────────

    [Fact]
    public void Create_MaxImagesZero_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { AllowImages = true, MaxImages = 0 };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.MaxImages);
    }

    [Fact]
    public void Create_MaxImagesNegative_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { AllowImages = true, MaxImages = -1 };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.MaxImages);
    }

    [Fact]
    public void Create_MaxImageSizeMBZero_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { MaxImageSizeMB = 0.0m };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.MaxImageSizeMB);
    }

    [Fact]
    public void Create_MaxImageWidthZero_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { MaxImageWidth = 0 };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.MaxImageWidth);
    }

    [Fact]
    public void Create_MaxImageHeightZero_FailsValidation()
    {
        var cmd = ValidCreateCommand() with { MaxImageHeight = 0 };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.MaxImageHeight);
    }

    // ── Create: valid commands pass ───────────────────────────────────────────

    [Fact]
    public void Create_ValidCommand_Passes()
    {
        var result = _createValidator.TestValidate(ValidCreateCommand());
        result.ShouldNotHaveAnyValidationErrors();
    }

    [Fact]
    public void Create_AllowImagesFalse_WithMaxImagesSet_Passes()
    {
        // Normalization is handler's responsibility, not validator's
        var cmd = ValidCreateCommand() with { AllowImages = false, MaxImages = 5 };
        var result = _createValidator.TestValidate(cmd);
        result.ShouldNotHaveAnyValidationErrors();
    }

    // ── Update: inherits same rules + Id > 0 ─────────────────────────────────

    [Fact]
    public void Update_IdZero_FailsValidation()
    {
        var cmd = ValidUpdateCommand() with { Id = 0 };
        var result = _updateValidator.TestValidate(cmd);
        result.ShouldHaveValidationErrorFor(x => x.Id);
    }

    [Fact]
    public void Update_ValidCommand_Passes()
    {
        var result = _updateValidator.TestValidate(ValidUpdateCommand());
        result.ShouldNotHaveAnyValidationErrors();
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    private static CreateProductTypeCommand ValidCreateCommand() => new(
        Nombre: "Clasificados",
        HasDuration: false, RequiresText: false, RequiresCategory: false, IsBundle: false,
        AllowImages: false,
        MaxImages: null, MaxImageSizeMB: null, MaxImageWidth: null, MaxImageHeight: null);

    private static UpdateProductTypeCommand ValidUpdateCommand() => new(
        Id: 1,
        Nombre: "Clasificados",
        HasDuration: false, RequiresText: false, RequiresCategory: false, IsBundle: false,
        AllowImages: false,
        MaxImages: null, MaxImageSizeMB: null, MaxImageWidth: null, MaxImageHeight: null);
}
