<?php
declare(strict_types=1);

/* =====================================================
   HEADER EXTRACTION
   ===================================================== */

function get_bearer_header(): ?string
{
    if (function_exists('getallheaders')) {
        $headers = getallheaders();

        if (!empty($headers['X-Authorization'])) {
            return trim($headers['X-Authorization']);
        }

        if (!empty($headers['Authorization'])) {
            return trim($headers['Authorization']);
        }
    }

    if (!empty($_SERVER['HTTP_X_AUTHORIZATION'])) {
        return trim($_SERVER['HTTP_X_AUTHORIZATION']);
    }

    if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
        return trim($_SERVER['HTTP_AUTHORIZATION']);
    }

    return null;
}

/* =====================================================
   REQUIRE AUTH (SESSION + TOKEN)
   ===================================================== */

function require_auth(PDO $pdo): array
{
    if (session_status() !== PHP_SESSION_ACTIVE) {
        session_start();
    }

    /* =====================================================
       INTERNAL USER FETCH (AUTHORITATIVE)
       ===================================================== */

    $fetchUser = function (int $userId) use ($pdo): array {

        $stmt = $pdo->prepare("
            SELECT
                u.id,
                u.email,
                u.role_key,
                u.company_id,
                u.email_verified,
                u.status,
                c.product_id,
                c.rsp_id,
                r.rank AS role_rank
            FROM users u
            LEFT JOIN companies c ON c.id = u.company_id
            INNER JOIN roles r ON r.role_key = u.role_key
            WHERE u.id = :id
              AND u.deleted_at IS NULL
            LIMIT 1
        ");

        $stmt->execute(['id' => $userId]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$user) {
            http_response_code(401);
            echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
            exit;
        }

        /* =========================
           ACCOUNT STATE ENFORCEMENT
           ========================= */

        if ($user['status'] !== 'active') {
            http_response_code(401);
            echo json_encode(['status' => 'error', 'message' => 'Account not active']);
            exit;
        }

        if ((int)$user['email_verified'] !== 1) {
            http_response_code(401);
            echo json_encode(['status' => 'error', 'message' => 'Email not verified']);
            exit;
        }

        /* =========================
           NORMALIZE ROLE
           ========================= */

        $roleKey = strtolower(trim((string)$user['role_key']));

        if (!$roleKey) {
            http_response_code(401);
            echo json_encode(['status' => 'error', 'message' => 'Invalid role']);
            exit;
        }

        $user['role_key']   = $roleKey;
        $user['role_rank']  = (int)$user['role_rank'];
        $user['product_id'] = (int)$user['product_id'];
        $user['rsp_id']     = (int)$user['rsp_id'];
        $user['company_id'] = (int)$user['company_id'];

        $user['is_global'] = in_array(
            $roleKey,
            ['super_admin', 'support'],
            true
        );

        return $user;
    };

    /* =====================================================
       1. SESSION AUTH
       ===================================================== */

    if (isset($_SESSION['user_id'])) {
        return $fetchUser((int)$_SESSION['user_id']);
    }

    /* =====================================================
       2. BEARER TOKEN AUTH
       ===================================================== */

    $auth = get_bearer_header();

    if (!$auth || !str_starts_with($auth, 'Bearer ')) {
        http_response_code(401);
        echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
        exit;
    }

    $token = substr($auth, 7);

    $stmt = $pdo->prepare("
        SELECT user_id
        FROM api_tokens
        WHERE token = :token
          AND revoked_at IS NULL
          AND expires_at > NOW()
        LIMIT 1
    ");

    $stmt->execute(['token' => $token]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
        http_response_code(401);
        echo json_encode(['status' => 'error', 'message' => 'Invalid token']);
        exit;
    }

    return $fetchUser((int)$row['user_id']);
}
