<?php
declare(strict_types=1);

namespace App\Middleware;

use Core\DB;
use Core\Middleware;
use Core\Tool;

/**
 * Validates `Authorization: Bearer <token>` against personal_access_tokens.
 * On success, populates $_SESSION so downstream middleware (TenantScope) and
 * controllers can read tenant_id + user info the same way as web requests.
 */
final class ApiToken implements Middleware
{
    public function handle(array $context): void
    {
        $header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
        if ($header === '' && function_exists('getallheaders')) {
            $all = getallheaders();
            $header = $all['Authorization'] ?? $all['authorization'] ?? '';
        }
        if (!preg_match('/Bearer\s+([A-Za-z0-9_\-\.]+)/i', $header, $m)) {
            json_response(['error' => 'Missing bearer token'], 401);
        }
        $hash = Tool::hashToken($m[1]);

        $row = DB::one(
            'SELECT t.token_id, t.tenant_id, t.user_id, t.expires_at, t.revoked_at,
                    u.username, u.f_name, u.l_name, u.email,
                    r.code AS role_code, r.name AS role_name
               FROM personal_access_tokens t
               JOIN users u ON u.user_id = t.user_id
          LEFT JOIN roles r ON r.role_id = u.role_id
              WHERE t.token_hash = :h
              LIMIT 1',
            ['h' => $hash]
        );

        if (!$row) json_response(['error' => 'Invalid token'], 401);
        if (!empty($row['revoked_at'])) json_response(['error' => 'Token revoked'], 401);
        if (!empty($row['expires_at']) && strtotime($row['expires_at']) < time()) {
            json_response(['error' => 'Token expired'], 401);
        }

        DB::run(
            'UPDATE personal_access_tokens SET last_used_at = NOW() WHERE token_id = :id',
            ['id' => $row['token_id']]
        );

        // Populate the same session shape web requests use, so TenantScope +
        // controllers can share code between web and API.
        $_SESSION['user'] = [
            'user_id'   => (int) $row['user_id'],
            'tenant_id' => (int) $row['tenant_id'],
            'username'  => $row['username'],
            'full_name' => trim(($row['f_name'] ?? '') . ' ' . ($row['l_name'] ?? '')),
            'email'     => $row['email'] ?? null,
            'role'      => $row['role_name'] ?? null,
            'role_code' => $row['role_code'] ?? null,
            'perms'     => [],
        ];
        $_SESSION['tenant_id'] = (int) $row['tenant_id'];
    }
}
