<?php

namespace MintyPHP\Tests\Architecture;

use PHPUnit\Framework\TestCase;

final class ConfigContractsTest extends TestCase
{
    use ProjectFileAssertionSupport;

    public function testConfigDirectoryContainsOnlyDeclarativeConfigFiles(): void
    {
        $required = [
            'config/assets.php',
            'config/routes.php',
            'config/modules.php',
            'config/config.php',
        ];
        foreach ($required as $file) {
            $this->assertFileExists($this->projectRootPath() . '/' . $file, 'Missing required config file: ' . $file);
        }

        $forbidden = [
            'config/router.php',
            'config/settings.php',
            'config/config.php.example',
        ];
        foreach ($forbidden as $file) {
            $this->assertFileDoesNotExist($this->projectRootPath() . '/' . $file, 'Forbidden runtime config file exists: ' . $file);
        }
    }

    public function testConfigDoesNotDefineLegacyRouteConstants(): void
    {
        $content = $this->readProjectFile('config/config.php');

        $this->assertStringNotContainsString('APP_ROUTE_DEFINITIONS', $content);
        $this->assertStringNotContainsString('APP_PUBLIC_PATHS', $content);
    }

    public function testRuntimePathsDoNotReferenceLegacyRouteConstants(): void
    {
        $runtimeFiles = $this->runtimeSourceFiles();
        $patterns = [
            '/\bAPP_ROUTE_DEFINITIONS\b/' => 'APP_ROUTE_DEFINITIONS',
            '/\bAPP_PUBLIC_PATHS\b/' => 'APP_PUBLIC_PATHS',
        ];

        $violations = [];
        foreach ($runtimeFiles as $relativePath) {
            $content = $this->readProjectFile($relativePath);
            foreach ($patterns as $regex => $label) {
                if (preg_match($regex, $content)) {
                    $violations[] = $relativePath . ': ' . $label;
                }
            }
        }

        $violations = array_values(array_unique($violations));
        sort($violations);

        $this->assertSame(
            [],
            $violations,
            "Legacy route constants referenced in runtime paths:\n" . implode("\n", $violations)
        );
    }

    /**
     * @return list<string>
     */
    private function runtimeSourceFiles(): array
    {
        $root = $this->projectRootPath();
        $scanTargets = ['core', 'pages', 'templates', 'web'];
        $extensions = ['php', 'phtml', 'js'];

        $files = [];
        foreach ($scanTargets as $target) {
            $fullPath = $root . '/' . $target;
            if (!is_dir($fullPath)) {
                continue;
            }

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

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

                $extension = strtolower((string) $file->getExtension());
                if (!in_array($extension, $extensions, true)) {
                    continue;
                }

                $files[] = str_replace($root . '/', '', $file->getPathname());
            }
        }

        $files = array_values(array_unique($files));
        sort($files);
        return $files;
    }
}
