<?php

declare(strict_types=1);

require dirname(__DIR__) . '/bootstrap.php';

use App\Models\Admission;

$baseUrl = rtrim((string) env('APP_URL', ''), '/');
$adminEmail = 'admin@empresa.com';
$adminPassword = 'TroqueEssaSenha123!';
$withWriteTests = in_array('--with-write-tests', $argv, true);

foreach ($argv as $arg) {
    if (str_starts_with($arg, '--base-url=')) {
        $baseUrl = rtrim(substr($arg, 11), '/');
    }
    if (str_starts_with($arg, '--email=')) {
        $adminEmail = substr($arg, 8);
    }
    if (str_starts_with($arg, '--password=')) {
        $adminPassword = substr($arg, 11);
    }
}

if ($baseUrl === '') {
    fwrite(STDERR, "APP_URL não definida. Configure no .env ou use --base-url=...\n");
    exit(1);
}

if (!function_exists('curl_init')) {
    fwrite(STDERR, "Extensão cURL não disponível.\n");
    exit(1);
}

$cookieJar = tempnam(sys_get_temp_dir(), 'adm-smoke-');
$results = [];
$failures = 0;

try {
    [$status, $body] = request('GET', $baseUrl . '/admin/login', null, $cookieJar);
    assertResult($results, $status === 200 && str_contains($body, 'name="_token"'), 'Abre login admin', $status === 200 ? 'Página OK.' : 'HTTP ' . $status, $failures);
    $token = extractToken($body);

    [$status, $body] = request('POST', $baseUrl . '/admin/login', [
        '_token' => $token,
        'email' => $adminEmail,
        'password' => $adminPassword,
    ], $cookieJar);
    assertResult($results, $status === 200 && str_contains($body, 'Painel RH'), 'Login admin', $status === 200 ? 'Autenticado com sucesso.' : 'Falha no login. HTTP ' . $status, $failures);

    [$status, $body] = request('GET', $baseUrl . '/admin/admissoes', null, $cookieJar);
    assertResult($results, $status === 200 && str_contains($body, 'Fichas de admissão') && str_contains($body, 'data-admin-live-search'), 'Lista de admissões', $status === 200 ? 'Lista carregada com busca instantânea.' : 'HTTP ' . $status, $failures);

    [$status, $body] = request('GET', $baseUrl . '/', null, $cookieJar);
    assertResult($results, $status === 200 && str_contains($body, 'name="full_name"'), 'Formulário público', $status === 200 ? 'Formulário carregado.' : 'HTTP ' . $status, $failures);

    [$status, $body] = request('POST', $baseUrl . '/admissoes', [
        '_token' => extractToken($body),
        'consent' => '1',
        'full_name' => '',
    ], $cookieJar);
    assertResult($results, $status === 200 && str_contains($body, 'Revise o formulário'), 'Validação de formulário inválido', $status === 200 ? 'Validação respondeu como esperado.' : 'HTTP ' . $status, $failures);

    $firstAdmission = Admission::search([])[0] ?? null;

    if ($firstAdmission) {
        [$status, $body] = request('GET', $baseUrl . '/admin/admissoes?search=' . urlencode((string) $firstAdmission['id']), null, $cookieJar);
        assertResult(
            $results,
            $status === 200
                && str_contains($body, 'data-admin-live-search')
                && str_contains($body, 'value="' . htmlspecialchars((string) $firstAdmission['id'], ENT_QUOTES, 'UTF-8') . '"')
                && str_contains($body, '#' . (string) $firstAdmission['id']),
            'Busca admin por ID',
            $status === 200 ? 'Busca instantânea preservou o termo e carregou a base.' : 'HTTP ' . $status,
            $failures
        );

        if (!empty($firstAdmission['status'])) {
            [$status, $body] = request('GET', $baseUrl . '/admin/admissoes?status=' . urlencode((string) $firstAdmission['status']), null, $cookieJar);
            assertResult(
                $results,
                $status === 200 && str_contains($body, 'name="status"'),
                'Filtro admin por status',
                $status === 200 ? 'Filtro de status respondeu.' : 'HTTP ' . $status,
                $failures
            );
        }

        [$status, $body] = request('GET', $baseUrl . '/admin/admissoes/' . $firstAdmission['id'], null, $cookieJar);
        assertResult($results, $status === 200 && str_contains($body, 'Status da ficha'), 'Detalhe da ficha', $status === 200 ? 'Detalhe carregado.' : 'HTTP ' . $status, $failures);

        $detailToken = extractToken($body);
        [$status, $body] = request('POST', $baseUrl . '/admin/admissoes/' . $firstAdmission['id'] . '/status', [
            '_token' => $detailToken,
            'status' => 'aprovado',
        ], $cookieJar);
        assertResult($results, $status === 200 && str_contains($body, 'Status do colaborador atualizado com sucesso'), 'Troca de status', $status === 200 ? 'Status alterado via formulário.' : 'HTTP ' . $status, $failures);
    } else {
        $results[] = ['ok' => false, 'label' => 'Troca de status', 'details' => 'Nenhuma admissão disponível para o teste. Rode seed_homologation primeiro.'];
        $failures++;
    }

    [$status, $body] = request('GET', $baseUrl . '/admin/usuarios', null, $cookieJar);
    assertResult($results, $status === 200 && str_contains($body, 'Usuários do painel'), 'Lista de admins', $status === 200 ? 'Lista carregada.' : 'HTTP ' . $status, $failures);

    if ($withWriteTests) {
        [$status, $body] = request('GET', $baseUrl . '/admin/usuarios/novo', null, $cookieJar);
        $createToken = extractToken($body);
        $randomEmail = 'smoke.' . date('YmdHis') . '@teste.local';
        [$status, $body] = request('POST', $baseUrl . '/admin/usuarios', [
            '_token' => $createToken,
            'name' => 'Smoke Test',
            'email' => $randomEmail,
            'password' => 'SmokeTest123!',
            'password_confirmation' => 'SmokeTest123!',
            'is_active' => '1',
        ], $cookieJar);
        assertResult($results, $status === 200 && str_contains($body, 'Usuário do painel criado com sucesso'), 'Criação de admin', $status === 200 ? 'Admin criado para smoke test.' : 'HTTP ' . $status, $failures);
    }
} finally {
    if (is_file($cookieJar)) {
        @unlink($cookieJar);
    }
}

echo "\n=== Smoke test HTTP ===\n\n";
foreach ($results as $result) {
    $prefix = $result['ok'] ? "\033[32mOK\033[0m" : "\033[31mFALHA\033[0m";
    echo sprintf('[%s] %s - %s%s', $prefix, $result['label'], $result['details'], PHP_EOL);
}

echo "\nFalhas: {$failures}\n";
exit($failures > 0 ? 1 : 0);

function request(string $method, string $url, ?array $data, string $cookieJar): array
{
    $ch = curl_init($url);

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_COOKIEJAR => $cookieJar,
        CURLOPT_COOKIEFILE => $cookieJar,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_USERAGENT => 'AdmissoesSmoke/1.0',
    ]);

    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data ?? []));
    }

    $body = curl_exec($ch);
    $status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    if ($body === false) {
        throw new RuntimeException('Falha HTTP: ' . $error);
    }

    return [$status, $body];
}

function extractToken(string $html): string
{
    if (preg_match('/name="_token"\s+value="([^"]+)"/', $html, $matches)) {
        return html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
    }

    throw new RuntimeException('Token CSRF não encontrado na página.');
}

function assertResult(array &$results, bool $ok, string $label, string $details, int &$failures): void
{
    $results[] = ['ok' => $ok, 'label' => $label, 'details' => $details];

    if (!$ok) {
        $failures++;
    }
}
