using FluentValidation;
using Meezi.API.Models.Menu;
using Meezi.API.Models.Orders;
using Meezi.API.Models.Tables;
using Meezi.Core.Constants;
using Meezi.Core.Utilities;

namespace Meezi.API.Validators;

public class CreateMenuCategoryRequestValidator : AbstractValidator<CreateMenuCategoryRequest>
{
    public CreateMenuCategoryRequestValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
        RuleFor(x => x.NameEn).NotEmpty().MaximumLength(200);
        RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0);
        RuleFor(x => x.DiscountPercent).InclusiveBetween(0, 100);
        RuleFor(x => x.Icon).MaximumLength(32).When(x => x.Icon is not null);
        RuleFor(x => x.IconPresetId)
            .Must(id => id is null || CategoryIconPresets.IsValidPreset(id))
            .WithMessage("Invalid icon preset.")
            .MaximumLength(48)
            .When(x => x.IconPresetId is not null);
        RuleFor(x => x.IconStyle)
            .Must(s => s is null || CategoryIconPresets.IsValidStyle(s))
            .WithMessage("Invalid icon style.")
            .MaximumLength(16)
            .When(x => x.IconStyle is not null);
        RuleFor(x => x.ImageUrl).MaximumLength(500).When(x => x.ImageUrl is not null);
        RuleFor(x => x)
            .Must(x => string.IsNullOrWhiteSpace(x.IconPresetId) == string.IsNullOrWhiteSpace(x.IconStyle))
            .WithMessage("Icon preset and style must be set together.");
    }
}

public class CreateMenuItemRequestValidator : AbstractValidator<CreateMenuItemRequest>
{
    public CreateMenuItemRequestValidator()
    {
        RuleFor(x => x.CategoryId).NotEmpty();
        RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
        RuleFor(x => x.NameEn).NotEmpty().MaximumLength(200);
        RuleFor(x => x.Price).GreaterThanOrEqualTo(0);
        RuleFor(x => x.DiscountPercent).InclusiveBetween(0, 100);
    }
}

public class CreateTableRequestValidator : AbstractValidator<CreateTableRequest>
{
    public CreateTableRequestValidator()
    {
        RuleFor(x => x.Number).NotEmpty().MaximumLength(50);
        RuleFor(x => x.Capacity).GreaterThan(0);
    }
}

public class PatchTableRequestValidator : AbstractValidator<PatchTableRequest>
{
    public PatchTableRequestValidator()
    {
        RuleFor(x => x.Number).NotEmpty().MaximumLength(50).When(x => x.Number is not null);
        RuleFor(x => x.Capacity).GreaterThan(0).When(x => x.Capacity.HasValue);
    }
}

public class CreateBranchTableRequestValidator : AbstractValidator<CreateBranchTableRequest>
{
    public CreateBranchTableRequestValidator()
    {
        RuleFor(x => x.Number).NotEmpty().MaximumLength(50);
        RuleFor(x => x.Capacity).GreaterThan(0);
    }
}

public class PatchBranchTableRequestValidator : AbstractValidator<PatchBranchTableRequest>
{
    public PatchBranchTableRequestValidator()
    {
        RuleFor(x => x.Number).NotEmpty().MaximumLength(50).When(x => x.Number is not null);
        RuleFor(x => x.Capacity).GreaterThan(0).When(x => x.Capacity.HasValue);
    }
}

public class CreateTableSectionRequestValidator : AbstractValidator<CreateTableSectionRequest>
{
    public CreateTableSectionRequestValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
    }
}

public class PatchTableSectionRequestValidator : AbstractValidator<PatchTableSectionRequest>
{
    public PatchTableSectionRequestValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(100).When(x => x.Name is not null);
    }
}

public class CreateOrderRequestValidator : AbstractValidator<CreateOrderRequest>
{
    public CreateOrderRequestValidator()
    {
        RuleFor(x => x.OrderType).IsInEnum();
        RuleFor(x => x.Items).NotEmpty();
        RuleFor(x => x.GuestName).MaximumLength(200).When(x => x.GuestName is not null);
        RuleFor(x => x.GuestPhone)
            .Must(p => PhoneNormalizer.IsValidIranMobile(PhoneNormalizer.Normalize(p!)))
            .When(x => !string.IsNullOrWhiteSpace(x.GuestPhone));
        RuleForEach(x => x.Items).ChildRules(item =>
        {
            item.RuleFor(i => i.MenuItemId).NotEmpty();
            item.RuleFor(i => i.Quantity).GreaterThan(0);
        });
    }
}

public class UpdateOrderStatusRequestValidator : AbstractValidator<UpdateOrderStatusRequest>
{
    public UpdateOrderStatusRequestValidator()
    {
        RuleFor(x => x.Status).IsInEnum();
    }
}

public class RecordPaymentsRequestValidator : AbstractValidator<RecordPaymentsRequest>
{
    public RecordPaymentsRequestValidator()
    {
        RuleFor(x => x.Payments).NotEmpty();
        RuleForEach(x => x.Payments).ChildRules(p =>
        {
            p.RuleFor(x => x.Method).IsInEnum();
            p.RuleFor(x => x.Amount).GreaterThan(0);
        });
        RuleFor(x => x.LoyaltyPointsToRedeem)
            .GreaterThanOrEqualTo(0)
            .When(x => x.LoyaltyPointsToRedeem.HasValue);
    }
}

public class AppendOrderItemsRequestValidator : AbstractValidator<AppendOrderItemsRequest>
{
    public AppendOrderItemsRequestValidator()
    {
        RuleFor(x => x.Items).NotEmpty();
        RuleForEach(x => x.Items).ChildRules(item =>
        {
            item.RuleFor(i => i.MenuItemId).NotEmpty();
            item.RuleFor(i => i.Quantity).GreaterThan(0);
        });
    }
}

public class UpdateOrderSessionRequestValidator : AbstractValidator<UpdateOrderSessionRequest>
{
    public UpdateOrderSessionRequestValidator()
    {
        RuleFor(x => x.GuestName).MaximumLength(200).When(x => x.GuestName is not null);
        RuleFor(x => x.GuestPhone)
            .Must(p => PhoneNormalizer.IsValidIranMobile(PhoneNormalizer.Normalize(p!)))
            .When(x => !string.IsNullOrWhiteSpace(x.GuestPhone));
    }
}

public class SetTableCleaningRequestValidator : AbstractValidator<SetTableCleaningRequest>
{
    public SetTableCleaningRequestValidator() { }
}
