using FluentValidation;
using IamService.API.Application.Commands.AccessRequests;

namespace IamService.API.Application.Validations;

/// <summary>
/// EN: Validator for CreateAccessRequestCommand.
/// VI: Validator cho CreateAccessRequestCommand.
/// </summary>
public class CreateAccessRequestCommandValidator : AbstractValidator<CreateAccessRequestCommand>
{
    private static readonly string[] ValidResourceTypes = ["Organization", "Group", "Role", "Application", "Resource"];

    public CreateAccessRequestCommandValidator()
    {
        RuleFor(x => x.RequesterId)
            .NotEmpty().WithMessage("Requester ID is required");

        RuleFor(x => x.ResourceType)
            .NotEmpty().WithMessage("Resource type is required")
            .MaximumLength(100).WithMessage("Resource type cannot exceed 100 characters")
            .Must(t => ValidResourceTypes.Contains(t))
            .WithMessage($"Resource type must be one of: {string.Join(", ", ValidResourceTypes)}");

        RuleFor(x => x.ResourceId)
            .NotEmpty().WithMessage("Resource ID is required");

        RuleFor(x => x.RequestedPermission)
            .NotEmpty().WithMessage("Requested permission is required")
            .MaximumLength(100).WithMessage("Requested permission cannot exceed 100 characters");

        RuleFor(x => x.Justification)
            .MaximumLength(2000).WithMessage("Justification cannot exceed 2000 characters")
            .When(x => x.Justification != null);

        RuleFor(x => x.Priority)
            .Must(p => p == null || (p >= 1 && p <= 4))
            .WithMessage("Priority must be 1 (Low), 2 (Medium), 3 (High), or 4 (Critical)");

        RuleFor(x => x.ApproverIds)
            .NotEmpty().WithMessage("At least one approver is required")
            .Must(ids => ids.All(id => id != Guid.Empty))
            .WithMessage("All approver IDs must be valid GUIDs");
    }
}

/// <summary>
/// EN: Validator for ApproveAccessRequestCommand.
/// VI: Validator cho ApproveAccessRequestCommand.
/// </summary>
public class ApproveAccessRequestCommandValidator : AbstractValidator<ApproveAccessRequestCommand>
{
    public ApproveAccessRequestCommandValidator()
    {
        RuleFor(x => x.RequestId)
            .NotEmpty().WithMessage("Request ID is required");

        RuleFor(x => x.ApproverId)
            .NotEmpty().WithMessage("Approver ID is required");

        RuleFor(x => x.Comments)
            .MaximumLength(1000).WithMessage("Comments cannot exceed 1000 characters")
            .When(x => x.Comments != null);
    }
}

/// <summary>
/// EN: Validator for RejectAccessRequestCommand.
/// VI: Validator cho RejectAccessRequestCommand.
/// </summary>
public class RejectAccessRequestCommandValidator : AbstractValidator<RejectAccessRequestCommand>
{
    public RejectAccessRequestCommandValidator()
    {
        RuleFor(x => x.RequestId)
            .NotEmpty().WithMessage("Request ID is required");

        RuleFor(x => x.ApproverId)
            .NotEmpty().WithMessage("Approver ID is required");

        RuleFor(x => x.Reason)
            .MaximumLength(1000).WithMessage("Reason cannot exceed 1000 characters")
            .When(x => x.Reason != null);
    }
}

/// <summary>
/// EN: Validator for SubmitAccessRequestCommand.
/// VI: Validator cho SubmitAccessRequestCommand.
/// </summary>
public class SubmitAccessRequestCommandValidator : AbstractValidator<SubmitAccessRequestCommand>
{
    public SubmitAccessRequestCommandValidator()
    {
        RuleFor(x => x.RequestId)
            .NotEmpty().WithMessage("Request ID is required");
    }
}

/// <summary>
/// EN: Validator for CancelAccessRequestCommand.
/// VI: Validator cho CancelAccessRequestCommand.
/// </summary>
public class CancelAccessRequestCommandValidator : AbstractValidator<CancelAccessRequestCommand>
{
    public CancelAccessRequestCommandValidator()
    {
        RuleFor(x => x.RequestId)
            .NotEmpty().WithMessage("Request ID is required");
    }
}
