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 CreateDocumentRequestValidator : AbstractValidator<CreateDocumentRequest>
    {
        public CreateDocumentRequestValidator(IDocumentCabinetRepository documentCabinetRepository)
        {
            RuleFor(x => x.DocumentName)
                .NotNull().NotEmpty().WithMessage("DocumentName is required")
                .MaximumLength(255).WithMessage("DocumentName must not exceed 255 characters.");
            
            RuleFor(x => x.DocumentTemplateId)
                .GreaterThan(0)
                .WithMessage("Document Template name is required and should be greater than 0.");
            
            RuleFor(x => x.DocumentTemplateName)
                .NotNull().NotEmpty().WithMessage("Document Template name is required and should not be empty.");
            
            RuleFor(x => x.DocumentFile)
                .NotNull().WithMessage("DocumentFile is required")
                .Must(BeValidFile).WithMessage("Document file must represent a valid file");
            
            RuleFor(x => x)
                .Must(x => documentCabinetRepository
                    .AnyAsync(cabinet =>
                        cabinet.CabinetName == x.DocumentTemplateName && cabinet.CabinetId == x.DocumentTemplateId).Result)
                .WithMessage(x =>
                    $"Document template with combination of Document Template Name '{x.DocumentTemplateName}' and Document Template ID '{x.DocumentTemplateId}' does not exist.");
            
            RuleForEach(x => x.DocumentFields)
                .Where(field => field.FieldType == ATDocumentFieldType.String)
                .ChildRules(field =>
                {
                    field.RuleFor(f => f.FieldValue)
                        .MaximumLength(255)
                        .WithMessage("Field value must not exceed 255 characters for String type.");
                });
            
            RuleFor(x => x.DocumentFields)
                .ForEach(field =>
                    field.Must(fieldItem => TypeHelpers.IsParsable(fieldItem.FieldType, fieldItem.FieldValue))
                        .WithMessage((fields, fieldItem) =>
                            $"Field value '{fieldItem.FieldValue}' is not parsable to '{fieldItem.FieldType}' type."));
        }

        private bool BeValidFile(string documentFile)
        {
            if (string.IsNullOrWhiteSpace(documentFile))
                return false;

            try
            {
                // Attempt to decode the Base64 string into a byte array
                byte[] fileBytes = Convert.FromBase64String(documentFile);

                // Validate that the byte array represents a valid file (non-empty)
                return fileBytes.Length > 0;
            }
            catch
            {
                return false;
            }
        }
    }
}
