<?php

namespace MintyPHP\Tests\Architecture;

use PHPUnit\Framework\TestCase;

/**
 * Views (.phtml) must be pure rendering — no database calls allowed.
 * All data must be prepared in actions and passed via view variables.
 */
class ViewLayerNoDbCallsContractTest extends TestCase
{
    use ProjectFileAssertionSupport;

    /** @var list<string> */
    private const DB_PATTERNS = [
        '/->query\s*\(/',
        '/->prepare\s*\(/',
        '/->execute\s*\(/',
        '/->fetch\s*\(/',
        '/->fetchAll\s*\(/',
        '/->fetchColumn\s*\(/',
        '/\bnew\s+PDO\b/',
        '/\$pdo\b/',
    ];

    public function testCorePagesViewsContainNoDbCalls(): void
    {
        $this->assertNoDbCallsInViews('pages');
    }

    public function testModuleViewsContainNoDbCalls(): void
    {
        $root = $this->projectRootPath();
        $modulesDir = $root . '/modules';
        if (!is_dir($modulesDir)) {
            self::markTestSkipped('modules/ directory missing.');
        }

        foreach (scandir($modulesDir) ?: [] as $entry) {
            if ($entry === '.' || $entry === '..' || !is_dir($modulesDir . '/' . $entry)) {
                continue;
            }
            $pagesRel = 'modules/' . $entry . '/pages';
            if (is_dir($root . '/' . $pagesRel)) {
                $this->assertNoDbCallsInViews($pagesRel);
            }
        }
    }

    public function testTemplatesContainNoDbCalls(): void
    {
        $this->assertNoDbCallsInViews('templates');
    }

    private function assertNoDbCallsInViews(string $relativeDirectory): void
    {
        $allViolations = [];

        foreach (self::DB_PATTERNS as $pattern) {
            $hits = $this->findPatternMatchesInFiles($relativeDirectory, $pattern, ['phtml']);
            foreach ($hits as $file) {
                $allViolations[$file] = true;
            }
        }

        $violations = array_keys($allViolations);
        sort($violations);

        self::assertSame(
            [],
            $violations,
            "Views must not contain database calls. Violations found:\n" . implode("\n", $violations)
        );
    }
}
