<?php

namespace MintyPHP\Tests\Architecture;

use PHPUnit\Framework\TestCase;

/**
 * Service layer (Service, Gateway, Policy) must not contain HTML output.
 * HTML rendering belongs in views (.phtml) and templates only.
 *
 * Excluded: PDF services that legitimately build HTML for Dompdf rendering.
 */
class ServiceLayerNoHtmlContractTest extends TestCase
{
    use ProjectFileAssertionSupport;

    /** @var list<string> */
    private const EXCLUDED_FILES = [
        'core/Service/User/UserAccessPdfService.php',
    ];

    /**
     * Matches opening HTML tags that indicate rendering logic.
     * Ignores comments and string literals containing tag descriptions.
     */
    private const HTML_TAG_PATTERN = '/<(?:div|span|table|form|input|button|select|textarea|label|ul|ol|li|h[1-6]|thead|tbody|tr|td|th|section|article|nav|header|footer|main|aside)\b/';

    public function testServicesContainNoHtmlTags(): void
    {
        $violations = $this->findHtmlViolations('core/Service');
        $violations = array_merge($violations, $this->findHtmlViolations('core/Http'));

        self::assertSame(
            [],
            $violations,
            "Service layer must not contain HTML tags. Violations found:\n" . implode("\n", $violations)
        );
    }

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

        $violations = [];
        foreach (scandir($modulesDir) ?: [] as $entry) {
            if ($entry === '.' || $entry === '..' || !is_dir($modulesDir . '/' . $entry)) {
                continue;
            }
            $libRel = 'modules/' . $entry . '/lib';
            if (is_dir($root . '/' . $libRel)) {
                $violations = array_merge($violations, $this->findHtmlViolations($libRel));
            }
        }

        self::assertSame(
            [],
            $violations,
            "Module service layer must not contain HTML tags. Violations found:\n" . implode("\n", $violations)
        );
    }

    /**
     * @return list<string>
     */
    private function findHtmlViolations(string $relativeDirectory): array
    {
        $root = $this->projectRootPath();
        $basePath = $root . '/' . $relativeDirectory;
        if (!is_dir($basePath)) {
            return [];
        }

        $hits = $this->findPatternMatchesInPhpFiles($relativeDirectory, self::HTML_TAG_PATTERN);

        return array_values(array_filter(
            $hits,
            static function (string $path): bool {
                // Exclude files that legitimately build HTML (PDF rendering)
                foreach (self::EXCLUDED_FILES as $excluded) {
                    if ($path === $excluded) {
                        return false;
                    }
                }

                // Only flag Service/Gateway/Policy/Factory files, not generic helpers
                return (bool) preg_match('/(Service|Gateway|Policy|Factory)\.php$/', $path);
            }
        ));
    }
}
