<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\DI\Verification;

use PpPhp\Core\Platform\DI\Compiler\Factory\FactoryCachePaths;
use PpPhp\Core\Platform\DI\Integration\PlatformContainerRuntime;
use PpPhp\Core\Platform\DI\Validation\ContainerValidator;
use PpPhp\Core\Platform\DI\Validation\DefinitionModelFinalizer;

final class DiSubsystemVerifier
{
    public function verify(string $basePath, bool $compile = true): DiSubsystemStatus
    {
        $checks = [];
        $issues = [];

        $definitionIssues = (new DefinitionModelFinalizer())->validate();
        $checks['definitionModel'] = $definitionIssues === [];
        foreach ($definitionIssues as $issue) {
            $issues[] = ['check' => 'definitionModel', 'message' => $issue];
        }

        $runtime = new PlatformContainerRuntime($basePath);
        $container = $runtime->container();
        $summary = $runtime->summary();

        $checks['runtimeDefinitions'] = ($summary['definitions'] ?? 0) >= 20;
        if (!$checks['runtimeDefinitions']) {
            $issues[] = ['check' => 'runtimeDefinitions', 'message' => 'Runtime container has too few definitions.'];
        }

        $validation = (new ContainerValidator())->validate($container->definitionRepository());
        $checks['validation'] = $validation->ok();
        foreach ($validation->issues() as $issue) {
            $issues[] = ['check' => 'validation', 'message' => $issue->message(), 'serviceId' => $issue->serviceId()];
        }

        $compileResult = null;
        if ($compile) {
            $compileResult = $runtime->compile();
            $factorySummary = $compileResult['report']['metadata']['factoryGeneration'] ?? ['generated' => 0, 'attempted' => 0, 'failed' => 0];

            $checks['compilerPipeline'] = in_array('definition-compilation', $compileResult['report']['stages'] ?? [], true)
                && in_array('factory-generation', $compileResult['report']['stages'] ?? [], true);

            $checks['factoryGeneration'] = ($factorySummary['attempted'] ?? 0) > 0
                && ($factorySummary['generated'] ?? 0) === ($factorySummary['attempted'] ?? -1)
                && ($factorySummary['failed'] ?? 1) === 0;

            $factoryFiles = is_dir(FactoryCachePaths::directory($basePath))
                ? glob(FactoryCachePaths::directory($basePath) . '/*.php')
                : [];

            $checks['factoryFiles'] = count($factoryFiles ?: []) >= ($factorySummary['generated'] ?? 0);

            if (!$checks['compilerPipeline']) {
                $issues[] = ['check' => 'compilerPipeline', 'message' => 'Expected compiler stages were not executed.'];
            }
            if (!$checks['factoryGeneration']) {
                $issues[] = ['check' => 'factoryGeneration', 'message' => 'Factory generation count is not clean.', 'summary' => $factorySummary];
            }
            if (!$checks['factoryFiles']) {
                $issues[] = ['check' => 'factoryFiles', 'message' => 'Factory files on disk are fewer than generated count.'];
            }
        }

        $allOk = !in_array(false, $checks, true);

        return new DiSubsystemStatus($allOk, $checks, [
            'definitions' => $summary['definitions'] ?? 0,
            'aliases' => $summary['aliases'] ?? 0,
            'tags' => $summary['tags'] ?? 0,
            'registered' => $summary['registered'] ?? 0,
            'validationScore' => $validation->score(),
            'compiledDefinitions' => $compileResult['report']['definitions'] ?? 0,
            'factoriesGenerated' => $compileResult['report']['metadata']['factoryGeneration']['generated'] ?? 0,
            'factoryFiles' => $compileResult['factoryFiles'] ?? 0,
        ], $issues);
    }
}
