using FluentValidation;
using IWS5.Core.Enums;
using IWS5.Core.Helpers;
using IWS5.Core.Models.Request;
using IWS5.DatabaseAccess.Interfaces;

namespace IWS5.Services.Validators;

public class AddDocumentRequestValidator : AbstractValidator<AddDocumentRequest>
{
    const int MaxFileSizeInBytes = 25 * 1024 * 1024; // 25 MB
    public AddDocumentRequestValidator(IDocumentCabinetRepository documentCabinetRepository, IWorkItemReferenceRepository workItemReferenceRepository, IProcessRepository processRepository)
    {
        RuleFor(x => x.ProcessId)
            .GreaterThan(0).WithMessage("Process ID must be greater than 0.")
            .Must(processId => processRepository.AnyAsync(p => p.ProcessId == processId).Result)
            .WithMessage("A process with the specified ID must exist in the repository.");
        
        RuleFor(x => x.DocumentName)
            .NotNull().NotEmpty().WithMessage("Document name is required.")
            .MaximumLength(255).WithMessage("Document name must not exceed 255 characters.")
            .Must(documentName => documentName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
            .WithMessage("Document name must be a PDF file (with a .pdf extension).");

        RuleFor(x => x.WorkItemId)
            .NotNull().WithMessage("Work item reference ID is required.")
            .GreaterThan(0).WithMessage("Work item reference ID is required and must be greater than 0.")
            .Must(workitemReferenceId =>workItemReferenceRepository.AnyAsync(w => w.WorkItemReferenceId == workitemReferenceId).Result)
            .WithMessage("A workItemId should be existing in the database.");

        RuleFor(x => x.DocumentTemplateId) 
            .NotNull().WithMessage("Document template ID is required.")
            .GreaterThan(0).WithMessage("Document template ID is required and must be greater than 0.");

        RuleFor(x => x.DocumentTemplateName)
            .NotNull().NotEmpty().WithMessage("Document template name is required.")
            .MaximumLength(255).WithMessage("Document template name must not exceed 255 characters.");

        RuleFor(x => x)
            .Must(request =>
            {
                if (request.DocumentTemplateId <= 0 || string.IsNullOrEmpty(request.DocumentTemplateName))
                    return false;

                var exists = documentCabinetRepository.AnyAsync(dc =>
                    dc.CabinetId == request.DocumentTemplateId &&
                    dc.CabinetName == request.DocumentTemplateName).Result;

                return exists;
            })
            .WithMessage("DocumentTemplateId and DocumentTemplateName must reference the same record in the database.");

        RuleFor(x => x.DocumentFile)
            .NotNull().NotEmpty().WithMessage("Document file is required.")
            .Must(file => file.Length <= MaxFileSizeInBytes)
            .WithMessage($"Document file size must not exceed { MaxFileSizeInBytes } MB.");
    }
}
