<?php declare(strict_types=1);

namespace Newland\ToubizWidgetRendering\Utility;

use Neos\Flow\Configuration\Exception\InvalidConfigurationException;
use Neos\Flow\Validation\Error;
use Neos\Utility\Arrays;
use Neos\Utility\SchemaValidator;
use Symfony\Component\Yaml\Yaml;
use function Safe\sprintf;
use Neos\Flow\Annotations as Flow;

class ValidationUtility
{
    protected const GENERAL_DEFINITIONS =
        'resource://Newland.ToubizWidgetRendering/Private/Schema/generalDefinitions.schema.yaml';

    /**
     * @var SchemaValidator
     * @Flow\Inject()
     */
    protected $schemaValidator;

    public function validateOrThrow(array $data, string $schemaFile): void
    {
        $schema = array_replace_recursive(
            Yaml::parseFile(static::GENERAL_DEFINITIONS),
            Yaml::parseFile($schemaFile)
        );

        $result = $this->schemaValidator->validate($data, $schema);

        if ($result->hasErrors()) {
            /** @var array<string, Error[]> $groupErrors */
            $groupErrors = $result->getFlattenedErrors();
            $messages = [];
            foreach ($groupErrors as $key => $errors) {
                foreach ($errors as $error) {
                    $messages[] = sprintf('- `%s`: %s', $key, $error->render());
                }
            }
            throw new InvalidConfigurationException(implode("\n", $messages));
        }
    }

    public function throwIfReferencedFilesDoNotExist(array $data, array $keysToCheck, string $message = ''): void
    {
        $missingFiles = [];
        foreach ($keysToCheck as $key) {
            $path = Arrays::getValueByPath($data, $key);
            if (!file_exists($path)) {
                $missingFiles[$key] = $path;
            }
        }

        if (count($missingFiles) === 0) {
            return;
        }

        $message .= 'The following files are missing:';
        foreach ($missingFiles as $key => $path) {
            $message .= sprintf("\n- Key '%s' references file '%s'", $key, $path);
        }

        throw new InvalidConfigurationException($message);
    }
}
