<?php

declare(strict_types=1);

it('keeps every selected API operation covered by happy-path and failure tests', function (): void {
    if (!api_tests_enabled()) {
        $this->markTestSkipped('API tests are disabled. Run with RUN_API_TESTS=1.');
    }

    $manifest = require app_path('tests/Api/api_coverage_manifest.php');
    $allOperations = array_merge($manifest['openapi_operations'], $manifest['manual_operations']);
    $happyOnlyOperations = $manifest['happy_only_operations'];
    $coverage = [];

    foreach (glob(app_path('tests/Api/*Test.php')) as $file) {
        if (basename($file) === 'ApiCoverageManifestTest.php') {
            continue;
        }

        $contents = (string)file_get_contents($file);
        preg_match_all(
            '/api_test_covers\(\s*[\'"]([^\'"]+)[\'"]\s*,\s*[\'"]([^\'"]+)[\'"]\s*\)/',
            $contents,
            $matches,
            PREG_SET_ORDER
        );

        foreach ($matches as $match) {
            $coverage[$match[1]][$match[2]] = true;
        }
    }

    foreach ($allOperations as $operation) {
        expect($coverage[$operation]['happy'] ?? false)
            ->toBeTrue('Missing happy-path coverage marker for ' . $operation . '.');

        if (in_array($operation, $happyOnlyOperations, true)) {
            continue;
        }

        expect(($coverage[$operation]['failure'] ?? false) || ($coverage[$operation]['auth'] ?? false))
            ->toBeTrue('Missing failure/auth coverage marker for ' . $operation . '.');
    }
});

it('keeps the OpenAPI manifest entries aligned with the API spec', function (): void {
    if (!api_tests_enabled()) {
        $this->markTestSkipped('API tests are disabled. Run with RUN_API_TESTS=1.');
    }

    $manifest = require app_path('tests/Api/api_coverage_manifest.php');
    $lines = file(app_path('openapi.yaml'), FILE_IGNORE_NEW_LINES);

    expect($lines)->not->toBeFalse();

    $operationsInSpec = [];
    $currentPath = null;
    foreach ($lines as $line) {
        if (preg_match('/^ {2}(\/[^:]+):\s*$/', $line, $pathMatch) === 1) {
            $currentPath = $pathMatch[1];
            continue;
        }

        if ($currentPath === null) {
            continue;
        }

        if (preg_match('/^ {4}([a-z]+):\s*$/', $line, $methodMatch) === 1) {
            $operationsInSpec[] = strtoupper($methodMatch[1]) . ' ' . $currentPath;
        }
    }

    foreach ($manifest['openapi_operations'] as $operation) {
        expect($operationsInSpec)->toContain($operation);
    }
});
