<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiModelLifecycleInvariantExpansionTest extends FullSurfaceE2EContractCase
{
    /** @test */
    public function create_update_show_index_lifecycle_routes_remain_controlled_for_core_resources(): void
    {
        $resourceFamilies = ['users', 'students', 'classes', 'parents', 'inventory', 'suppliers', 'invoices', 'payments', 'messages'];

        foreach ($resourceFamilies as $family) {
            $routes = $this->apiRoutesContainingAny([$family]);

            foreach (array_slice($routes, 0, 25) as $route) {
                $method = $this->primaryMethod($route);
                $uri = $route->uri();
                $response = $this->probeRoute($route);

                $this->assertControlled($response, $method, $uri);
                $this->assertLessThan(500, $response->getStatusCode(), "$method $uri lifecycle probe should not produce server errors.");
            }
        }
    }

    /** @test */
    public function identity_fields_are_not_overwritten_by_update_payloads(): void
    {
        $routes = array_slice(array_filter($this->apiRoutes(), function ($route): bool {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();

            return in_array($method, ['PUT', 'PATCH'], true)
                && str_contains($uri, '{')
                && str_contains($uri, 'api/');
        }), 0, 70);

        $poison = [
            'id' => 999999,
            'uuid' => 'attacker-supplied-uuid',
            'created_at' => '1900-01-01 00:00:00',
            'updated_at' => '1900-01-01 00:00:00',
            'deleted_at' => '1900-01-01 00:00:00',
            'created_by' => 999999,
            'updated_by' => 999999,
        ];

        foreach ($routes as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();
            $payload = $this->payloadFor($method, $uri) + $poison;

            $response = $this->requestAs($this->actorFor($uri), $method, $uri, $payload);

            $this->assertControlled($response, $method, $uri);
            $this->assertLessThan(500, $response->getStatusCode(), "$method $uri should not crash on immutable identity fields.");
        }
    }
}
