<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiDateMoneyAndTimezoneBoundaryContractTest extends FullSurfaceE2EContractCase
{
    public function test_date_accepting_endpoints_reject_impossible_or_ambiguous_dates_cleanly(): void
    {
        $badDates = [
            '2025-02-30',
            '2025-13-01',
            'not-a-date',
            '01/02/03',
            '9999-99-99',
        ];

        foreach ($this->apiRoutesContainingAny(['attendance', 'finance', 'reports', 'school-years', 'calendar', 'payments', 'invoices']) as $route) {
            $method = $this->primaryMethod($route);

            if (! in_array($method, ['GET', 'POST', 'PUT', 'PATCH'], true)) {
                continue;
            }

            foreach ($badDates as $badDate) {
                $payload = $this->payloadFor($method, $route->uri()) + [
                    'date' => $badDate,
                    'from' => $badDate,
                    'to' => $badDate,
                    'start_date' => $badDate,
                    'end_date' => $badDate,
                ];

                $response = $this->requestAs($this->actorFor($route->uri()), $method, $route->uri(), $payload);
                $this->assertStatusIn($response, [200, 204, 400, 403, 404, 409, 422], "{$method} {$route->uri()} bad date {$badDate}");
                $this->assertStringNotContainsString('SQLSTATE', $response->getContent());
            }
        }
    }

    public function test_money_accepting_endpoints_reject_negative_nan_and_overflow_amounts_cleanly(): void
    {
        $badAmounts = [-1, -0.01, 0, 'NaN', 'Infinity', '999999999999999999999999', '1e309'];

        foreach ($this->apiRoutesContainingAny(['finance', 'payments', 'refunds', 'invoices', 'fees', 'reimbursements', 'expenses']) as $route) {
            $method = $this->primaryMethod($route);

            if (! in_array($method, ['POST', 'PUT', 'PATCH'], true)) {
                continue;
            }

            foreach ($badAmounts as $amount) {
                $payload = $this->payloadFor($method, $route->uri()) + [
                    'amount' => $amount,
                    'paid_amount' => $amount,
                    'total' => $amount,
                    'unit_cost' => $amount,
                    'fee' => $amount,
                ];

                $response = $this->requestAs($this->actorFor($route->uri()), $method, $route->uri(), $payload);
                $this->assertStatusIn($response, [400, 403, 404, 409, 422], "{$method} {$route->uri()} should reject bad amount.");
                $this->assertStringNotContainsString('SQLSTATE', $response->getContent());
            }
        }
    }
}
