<?php

namespace MintyPHP\Tests\Architecture;

use PHPUnit\Framework\TestCase;

class CodexDocsIntegrityContractTest extends TestCase
{
    use CodexDocsContractSupport;
    use ProjectFileAssertionSupport;

    public function testCodexPromptsDocumentationReferencesBothSkills(): void
    {
        $prompts = $this->readProjectFile('docs/reference-codex-prompts.md');
        $this->assertStringContainsString('core-guardrails', $prompts);
        $this->assertStringContainsString('starterkit-planner', $prompts);
    }

    public function testDocsIndexReferencesCodexPrompts(): void
    {
        $index = $this->readProjectFile('docs/index.md');
        $this->assertStringContainsString('/docs/reference-codex-prompts.md', $index);
    }

    public function testDocumentationLinksResolveAcrossDocsSkillsAndAgentGuides(): void
    {
        foreach ($this->filesCoveredByDocsLinkIntegrityCheck() as $file) {
            $content = $this->readProjectFile($file);
            preg_match_all('/(?<![A-Za-z0-9_])\\/?docs\\/[a-z0-9_\\/-]+\\.md\\b/', $content, $matches);
            foreach (array_unique($matches[0]) as $link) {
                $normalized = ltrim($link, '/');
                $absolute = dirname(__DIR__, 2) . '/' . $normalized;
                $this->assertFileExists($absolute, sprintf('Broken docs link "%s" in %s', $link, $file));
            }
        }
    }

    public function testDocsIndexCoversAllMarkdownDocsWithoutOrphansOrDuplicates(): void
    {
        $index = $this->readProjectFile('docs/index.md');
        preg_match_all('/\\/docs\\/([a-z0-9-]+\\.md)\\b/', $index, $matches);
        $references = $matches[1];

        $docFiles = glob(dirname(__DIR__, 2) . '/docs/*.md');
        $this->assertNotFalse($docFiles, 'Failed to enumerate docs/*.md files.');

        $expectedDocs = [];
        foreach ($docFiles as $fullPath) {
            $basename = basename($fullPath);
            if ($basename !== 'index.md') {
                $expectedDocs[] = $basename;
            }
        }

        $refCounts = array_count_values($references);
        $duplicates = [];
        foreach ($refCounts as $ref => $count) {
            if ($count > 1) {
                $duplicates[] = $ref;
            }
        }

        $uniqueReferences = array_values(array_unique($references));
        sort($expectedDocs);
        sort($uniqueReferences);
        sort($duplicates);

        $orphans = array_values(array_diff($expectedDocs, $uniqueReferences));
        $missingTargets = array_values(array_diff($uniqueReferences, $expectedDocs));

        $this->assertSame([], $duplicates, 'Duplicate docs/index.md references: ' . implode(', ', $duplicates));
        $this->assertSame([], $orphans, 'Docs markdown files missing in docs/index.md: ' . implode(', ', $orphans));
        $this->assertSame([], $missingTargets, 'docs/index.md references missing files: ' . implode(', ', $missingTargets));
    }
}
