using Extrudex.API.DTOs.Spools;
using FluentValidation;

namespace Extrudex.API.Validators;

/// <summary>
/// Validation rules for creating a Spool.
/// </summary>
public class CreateSpoolRequestValidator : AbstractValidator<CreateSpoolRequest>
{
    public CreateSpoolRequestValidator()
    {
        RuleFor(x => x.MaterialBaseId)
            .NotEmpty().WithMessage("MaterialBaseId is required.");

        RuleFor(x => x.MaterialFinishId)
            .NotEmpty().WithMessage("MaterialFinishId is required.");

        RuleFor(x => x.Brand)
            .NotEmpty().WithMessage("Brand is required.")
            .MaximumLength(100).WithMessage("Brand must not exceed 100 characters.");

        RuleFor(x => x.ColorName)
            .NotEmpty().WithMessage("ColorName is required.")
            .MaximumLength(100).WithMessage("ColorName must not exceed 100 characters.");

        RuleFor(x => x.ColorHex)
            .NotEmpty().WithMessage("ColorHex is required.")
            .Matches(@"^#[0-9A-Fa-f]{6}$").WithMessage("ColorHex must be a valid hex color code (e.g., #FF0000).");

        RuleFor(x => x.WeightTotalGrams)
            .GreaterThan(0).WithMessage("Total weight must be greater than zero.");

        RuleFor(x => x.WeightRemainingGrams)
            .GreaterThanOrEqualTo(0).WithMessage("Remaining weight must be non-negative.");

        RuleFor(x => x.FilamentDiameterMm)
            .GreaterThan(0).WithMessage("Filament diameter must be greater than zero.");

        RuleFor(x => x.SpoolSerial)
            .NotEmpty().WithMessage("SpoolSerial is required.")
            .MaximumLength(100).WithMessage("SpoolSerial must not exceed 100 characters.");

        When(x => x.PurchasePrice.HasValue, () =>
        {
            RuleFor(x => x.PurchasePrice!.Value)
                .GreaterThanOrEqualTo(0).WithMessage("Purchase price must be non-negative.");
        });
    }
}

/// <summary>
/// Validation rules for updating a Spool.
/// </summary>
public class UpdateSpoolRequestValidator : AbstractValidator<UpdateSpoolRequest>
{
    public UpdateSpoolRequestValidator()
    {
        RuleFor(x => x.MaterialBaseId)
            .NotEmpty().WithMessage("MaterialBaseId is required.");

        RuleFor(x => x.MaterialFinishId)
            .NotEmpty().WithMessage("MaterialFinishId is required.");

        RuleFor(x => x.Brand)
            .NotEmpty().WithMessage("Brand is required.")
            .MaximumLength(100).WithMessage("Brand must not exceed 100 characters.");

        RuleFor(x => x.ColorName)
            .NotEmpty().WithMessage("ColorName is required.")
            .MaximumLength(100).WithMessage("ColorName must not exceed 100 characters.");

        RuleFor(x => x.ColorHex)
            .NotEmpty().WithMessage("ColorHex is required.")
            .Matches(@"^#[0-9A-Fa-f]{6}$").WithMessage("ColorHex must be a valid hex color code (e.g., #FF0000).");

        RuleFor(x => x.WeightTotalGrams)
            .GreaterThan(0).WithMessage("Total weight must be greater than zero.");

        RuleFor(x => x.WeightRemainingGrams)
            .GreaterThanOrEqualTo(0).WithMessage("Remaining weight must be non-negative.");

        RuleFor(x => x.FilamentDiameterMm)
            .GreaterThan(0).WithMessage("Filament diameter must be greater than zero.");

        RuleFor(x => x.SpoolSerial)
            .NotEmpty().WithMessage("SpoolSerial is required.")
            .MaximumLength(100).WithMessage("SpoolSerial must not exceed 100 characters.");

        When(x => x.PurchasePrice.HasValue, () =>
        {
            RuleFor(x => x.PurchasePrice!.Value)
                .GreaterThanOrEqualTo(0).WithMessage("Purchase price must be non-negative.");
        });
    }
}