<?php

namespace Tests\Feature\Api\V1\FullSurface;

use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;

class ApiContractSnapshotSeedTest extends FullSurfaceE2EContractCase
{
    public function test_core_success_payloads_keep_contract_keys_when_available(): void
    {
        foreach ($this->contractSamples() as $label => $sample) {
            $response = $this->requestAs($sample['actor'], $sample['method'], $sample['path'], $sample['payload'] ?? []);

            $this->assertStatusIn($response, [200, 201, 202, 204, 302, 400, 401, 403, 404, 405, 409, 419, 422], $label);
            $this->assertNoServerError($response, $label);

            if (in_array($response->getStatusCode(), [200, 201, 202], true) && $response->getContent() !== '' && $this->isJsonString($response->getContent())) {
                $flat = json_encode($response->json(), JSON_THROW_ON_ERROR);

                foreach ($sample['expected_any'] as $key) {
                    if (str_contains($flat, $key)) {
                        $this->assertTrue(true);
                        continue 2;
                    }
                }

                $this->fail($label . ' did not expose any expected contract key: ' . implode(', ', $sample['expected_any']));
            }
        }
    }

    public function test_auth_identity_payload_never_drops_user_identity_when_successful(): void
    {
        $response = $this->requestAs($this->admin, 'GET', 'api/v1/auth/me');

        $this->assertStatusIn($response, [200, 204, 302, 401, 403, 404, 405, 419, 422], 'GET api/v1/auth/me');
        $this->assertNoServerError($response, 'GET api/v1/auth/me');

        if ($response->getStatusCode() === 200 && $this->isJsonString($response->getContent())) {
            $flat = json_encode($response->json(), JSON_THROW_ON_ERROR);
            $this->assertStringContainsString('email', $flat, 'auth/me successful payload should expose identity email.');
            $this->assertStringContainsString('id', $flat, 'auth/me successful payload should expose identity id.');
        }
    }

    /** @return array<string,array{actor:mixed,method:string,path:string,payload?:array<string,mixed>,expected_any:list<string>}> */
    private function contractSamples(): array
    {
        return [
            'users index contract' => ['actor' => $this->admin, 'method' => 'GET', 'path' => 'api/v1/users', 'expected_any' => ['data', 'users', 'id', 'email']],
            'students index contract' => ['actor' => $this->admin, 'method' => 'GET', 'path' => 'api/v1/students', 'expected_any' => ['data', 'students', 'student_id', 'firstname']],
            'parent profile contract' => ['actor' => $this->parent, 'method' => 'GET', 'path' => 'api/v1/parents/profile', 'expected_any' => ['user', 'parent', 'email', 'firstname']],
            'teacher classes contract' => ['actor' => $this->teacher, 'method' => 'GET', 'path' => 'api/v1/teacher/classes', 'expected_any' => ['classes', 'class_section_id', 'data']],
            'finance invoices contract' => ['actor' => $this->admin, 'method' => 'GET', 'path' => 'api/v1/finance/invoices', 'expected_any' => ['invoice', 'amount', 'data', 'parent_id']],
            'inventory items contract' => ['actor' => $this->admin, 'method' => 'GET', 'path' => 'api/v1/inventory/items', 'expected_any' => ['item', 'quantity', 'data', 'name']],
        ];
    }
}
