<?php

declare(strict_types=1);

namespace PpPhp\Core\Maintenance\Providers;

use PpPhp\Core\Maintenance\Contracts\MaintenanceProviderInterface;
use PpPhp\Core\Maintenance\Results\MaintenanceResult;

final class ManifestBasicsProvider implements MaintenanceProviderInterface
{
    public function id(): string
    {
        return 'manifest-basics';
    }

    public function label(): string
    {
        return 'Manifest Basics';
    }

    public function description(): string
    {
        return 'Scans manifest.json files and reports missing universal manifest fields.';
    }

    public function priority(): int
    {
        return 20;
    }

    public function run(string $basePath): MaintenanceResult
    {
        $result = new MaintenanceResult($this->id(), $this->label());

        foreach ($this->manifestFiles($basePath) as $manifestFile) {
            $data = json_decode((string) file_get_contents($manifestFile), true);

            if (!is_array($data)) {
                $result->error('Invalid JSON manifest.', $manifestFile, 'Fix JSON syntax.');
                continue;
            }

            foreach (['id', 'type', 'label', 'version'] as $field) {
                if (!isset($data[$field]) || trim((string) $data[$field]) === '') {
                    $result->warning(
                        'Manifest missing required field: ' . $field,
                        $manifestFile,
                        'Add "' . $field . '" to make this manifest UMF-compliant.'
                    );
                }
            }
        }

        return $result;
    }

    /**
     * @return string[]
     */
    private function manifestFiles(string $basePath): array
    {
        $files = [];

        if (!is_dir($basePath)) {
            return $files;
        }

        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($basePath, \FilesystemIterator::SKIP_DOTS)
        );

        foreach ($iterator as $file) {
            if (!$file instanceof \SplFileInfo || !$file->isFile()) {
                continue;
            }

            $path = $file->getPathname();

            if (str_contains($path, DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR)) {
                continue;
            }

            if ($file->getFilename() === 'manifest.json') {
                $files[] = $path;
            }
        }

        sort($files);

        return $files;
    }
}
