<?php

namespace MintyPHP\Tests\Architecture;

use PHPUnit\Framework\TestCase;

/**
 * All CSS and JS asset references in templates and views must use
 * assetVersion() for cache-busting. Bare paths without assetVersion()
 * risk serving stale cached assets after deploys.
 *
 * Excluded: inline scripts, data URIs, external CDN URLs, and empty src attributes.
 */
class AssetVersioningContractTest extends TestCase
{
    use ProjectFileAssertionSupport;

    /**
     * Matches src="..." or href="..." pointing to local .js/.css files
     * that are NOT wrapped in assetVersion().
     *
     * The negative lookbehind ensures we don't flag assetVersion() usages.
     * Excludes external URLs (http://, https://, //) and empty attributes.
     */
    private const BARE_JS_PATTERN = '/src=["\'](?!https?:\/\/|\/\/)(?!<?php\s+e\(assetVersion)[^"\']*\.js["\']/';
    private const BARE_CSS_PATTERN = '/href=["\'](?!https?:\/\/|\/\/)(?!<?php\s+e\(assetVersion)[^"\']*\.css["\']/';

    public function testTemplateAssetReferencesUseAssetVersion(): void
    {
        $this->assertAssetVersionUsed('templates');
    }

    public function testCorePageAssetReferencesUseAssetVersion(): void
    {
        $this->assertAssetVersionUsed('pages');
    }

    public function testModulePageAssetReferencesUseAssetVersion(): 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;
            }

            foreach (['pages', 'templates'] as $subdir) {
                $rel = 'modules/' . $entry . '/' . $subdir;
                if (is_dir($root . '/' . $rel)) {
                    $this->assertAssetVersionUsed($rel);
                }
            }
        }
    }

    private function assertAssetVersionUsed(string $relativeDirectory): void
    {
        $jsViolations = $this->findPatternMatchesInFiles($relativeDirectory, self::BARE_JS_PATTERN, ['phtml']);
        $cssViolations = $this->findPatternMatchesInFiles($relativeDirectory, self::BARE_CSS_PATTERN, ['phtml']);

        $violations = array_unique(array_merge($jsViolations, $cssViolations));
        sort($violations);

        self::assertSame(
            [],
            $violations,
            "Asset references must use assetVersion() for cache-busting. Violations:\n" . implode("\n", $violations)
        );
    }
}
