package ru.soune.nocopy.handler.validator;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import ru.soune.nocopy.dto.file.FileUploadRequest;
import ru.soune.nocopy.entity.file.FileType;

import java.util.Arrays;
import java.util.List;

@Component
public class FileUploadRequestValidator implements Validator {
    private final List<FileType> supportedFileTypes = Arrays.asList(FileType.values());

    @Override
    public boolean supports(Class<?> clazz) {
        return FileUploadRequest.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        FileUploadRequest request = (FileUploadRequest) target;

        validateType(request.getFileType(), errors);
        validateFileName(request.getFileName(), errors);
        validateExtension(request.getExtension(), request.getFileType(), errors);
    }

    private void validateType(String fileType, Errors errors) {
        if (fileType == null || fileType.isBlank()) {
            errors.rejectValue("fileType", "fileType.required", "File type is required");
            return;
        }

        try {
            FileType parsedType = FileType.valueOf(fileType.toUpperCase());

            if (!supportedFileTypes.contains(parsedType)) {
                errors.rejectValue("fileType", "fileType.unsupported",
                        "Unsupported file type. Valid types: " + Arrays.toString(FileType.values()));
            }
        } catch (IllegalArgumentException e) {
            errors.rejectValue("fileType", "fileType.invalid",
                    "Invalid file type. Valid types: " + Arrays.toString(FileType.values()));
        }
    }

    private void validateFileName(String fileName, Errors errors) {
        if (fileName == null || fileName.isBlank()) {
            errors.rejectValue("fileName", "fileName.required", "File name is required");
            return;
        }

        if (fileName.length() > 255) {
            errors.rejectValue("fileName", "fileName.too.long",
                    "File name too long, max 255 characters");
        }
    }

    private void validateExtension(String extension, String fileType,  Errors errors) {
        if (extension == null || extension.isBlank()) {
            errors.rejectValue("fileType", "fileType.required", "File type is required");
            return;
        }

        if (extension.contains(".")) {
            errors.rejectValue("extension", "extension.required", "Extension contains comma");
            return;
        }

        try {
            FileType parsedType = FileType.valueOf(fileType.toUpperCase());

            if (!parsedType.supportsExtension(extension)) {
                errors.rejectValue("fileName", "fileType.extension.mismatch",
                        String.format("File extension '%s' does not match file type '%s'. Allowed extensions for %s: %s",
                                extension, parsedType.getDisplayName(), parsedType.getDisplayName(),
                                parsedType.getAllowedExtensions()));
            }

        } catch (IllegalArgumentException e) {
            errors.rejectValue("fileType", "fileType.invalid",
                    "Invalid file type. Valid types: " + Arrays.toString(FileType.values()));
        }
    }

    private String getFileExtension(String fileName) {
        return fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
    }
}