<?php

namespace Tests\Feature\Api\V1\FullSurface;

use Illuminate\Routing\Route as LaravelRoute;
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;

class ApiDeepPaginationSearchAndFilterContractTest extends FullSurfaceE2EContractCase
{
    public function test_list_endpoints_tolerate_pagination_search_sort_and_filter_parameters(): void
    {
        $failures = [];

        foreach ($this->listRoutes() as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();
            $path = $this->materializePath($uri) . '?' . http_build_query([
                'page' => 1,
                'per_page' => 10,
                'search' => 'e2e',
                'sort' => 'created_at',
                'direction' => 'desc',
                'school_year' => self::E2E_SCHOOL_YEAR,
                'semester' => self::E2E_SEMESTER,
                'status' => 'active',
            ]);

            $this->actingAs($this->actorFor($uri), 'api');
            $response = $this->json($method, $path);
            $status = $response->getStatusCode();

            if ($status >= 500) {
                $failures[] = "$method $uri crashed with list filters: " . $response->getContent();
                continue;
            }

            if (! in_array($status, [200, 204, 302, 400, 401, 403, 404, 405, 409, 422], true)) {
                $failures[] = "$method $uri returned unexpected $status with list filters: " . $response->getContent();
            }
        }

        $this->assertSame([], $failures, "List endpoints must not crash when clients send boring grid params:\n" . implode("\n", $failures));
    }

    public function test_date_range_filters_fail_cleanly_when_dates_are_invalid(): void
    {
        $failures = [];

        foreach ($this->dateFilterRoutes() as $route) {
            $uri = $route->uri();
            $path = $this->materializePath($uri) . '?' . http_build_query([
                'from' => 'not-a-date',
                'to' => 'still-not-a-date',
                'start_date' => '2025-99-99',
                'end_date' => 'yesterday-ish',
            ]);

            $this->actingAs($this->actorFor($uri), 'api');
            $response = $this->json('GET', $path);

            if ($response->getStatusCode() >= 500) {
                $failures[] = "GET $uri crashed on invalid date filters: " . $response->getContent();
            }
        }

        $this->assertSame([], $failures, "Invalid date filters should be validation, not detonation:\n" . implode("\n", $failures));
    }

    /** @return list<LaravelRoute> */
    private function listRoutes(): array
    {
        return array_values(array_filter($this->apiRoutes(), function (LaravelRoute $route): bool {
            $uri = $route->uri();

            return $this->primaryMethod($route) === 'GET'
                && ! preg_match('#/\{[^}]+\}$#', $uri)
                && ! str_contains($uri, 'download')
                && ! str_contains($uri, 'export')
                && ! str_contains($uri, 'pdf')
                && ! str_contains($uri, 'swagger');
        }));
    }

    /** @return list<LaravelRoute> */
    private function dateFilterRoutes(): array
    {
        return array_values(array_filter($this->listRoutes(), function (LaravelRoute $route): bool {
            $uri = $route->uri();

            return str_contains($uri, 'attendance')
                || str_contains($uri, 'finance')
                || str_contains($uri, 'reports')
                || str_contains($uri, 'payments')
                || str_contains($uri, 'invoices')
                || str_contains($uri, 'school-years');
        }));
    }
}
