<?php

declare(strict_types=1);

namespace App\Tests\Integration\App;

use App\Auth\UserContext;
use App\Tests\Integration\Support\AppTestCase;

/**
 * Smoke tests for the basic routing surface: home redirect, healthz,
 * /app/* gating, /no-access page.
 */
final class RoutesTest extends AppTestCase
{
    protected function setUp(): void
    {
        $this->bootApp();
    }

    public function testHomeRedirectsToLoginWhenAnonymous(): void
    {
        $response = $this->request('GET', '/');
        self::assertSame(302, $response->getStatusCode());
        self::assertSame('/login', $response->getHeaderLine('Location'));
    }

    public function testHomeRedirectsToDashboardWhenAuthenticated(): void
    {
        $_SESSION['_user'] = (new UserContext(1, 'Admin', 'admin', null, UserContext::SOURCE_LOCAL))->toArray();
        $_SESSION['_last_active'] = time();
        $_SESSION['_authenticated_at'] = time();

        $response = $this->request('GET', '/');
        self::assertSame(302, $response->getStatusCode());
        self::assertSame('/app/dashboard', $response->getHeaderLine('Location'));
    }

    public function testHealthzReturnsOk(): void
    {
        $response = $this->request('GET', '/healthz');
        self::assertSame(200, $response->getStatusCode());
        $body = json_decode((string) $response->getBody(), true);
        self::assertSame('ok', $body['status']);
        self::assertArrayHasKey('api_reachable', $body);
        self::assertArrayHasKey('last_api_check_at', $body);
    }

    public function testAppMeRedirectsAnonymousToLogin(): void
    {
        $response = $this->request('GET', '/app/me');
        self::assertSame(302, $response->getStatusCode());
        self::assertSame('/login', $response->getHeaderLine('Location'));
        self::assertSame('/app/me', $_SESSION['_next'] ?? null);
    }

    public function testAppMeRendersForLoggedInUser(): void
    {
        $_SESSION['_user'] = (new UserContext(7, 'Admin', 'admin', 'a@x', UserContext::SOURCE_LOCAL))->toArray();
        $_SESSION['_last_active'] = time();
        $_SESSION['_authenticated_at'] = time();
        $this->enqueueApiResponse(200, [
            'user_id' => 7, 'role' => 'admin', 'email' => 'a@x', 'display_name' => 'Admin', 'is_local' => true,
        ]);

        $response = $this->request('GET', '/app/me');

        self::assertSame(200, $response->getStatusCode());
        $body = (string) $response->getBody();
        self::assertStringContainsString('My identity', $body);
        self::assertStringContainsString('admin', $body);
        self::assertStringContainsString('7', $body);
    }

    public function testNoAccessPageRenders(): void
    {
        $response = $this->request('GET', '/no-access');
        self::assertSame(200, $response->getStatusCode());
        self::assertStringContainsString('No access', (string) $response->getBody());
    }
}
