<?php
// =============================================================
//  include/session_setup.php
//
//  Establishes the full authenticated session for a verified account —
//  extracted from login.php so app/verify_2fa.php can call the exact
//  same logic after a successful second-factor check, instead of a
//  second hand-copy that would inevitably drift from the original
//  (see: the forgot_password.php bug this same class of drift caused).
//
//  Callers must already have confirmed the account's identity (password,
//  and 2FA if enabled) before calling this — it does no verification of
//  its own.
//
//  hydrateRequestContext() below is the part of that logic every caller
//  needs — role/permissions, department/unit scope, table-specific
//  session keys — with no side effects (no DB writes). establishUserSession()
//  is that plus the web-login-only side effects (last_login stamp, audit
//  log, remember-me cookie). api/v1/_bootstrap.php calls
//  hydrateRequestContext() directly on every authenticated API request —
//  it populates $_SESSION as a per-request context bag (nothing sends it
//  back as a cookie for API calls), so PermissionManager, AuthMiddleware,
//  and every function in include/scope_helper.php work unmodified for
//  both the web app and the mobile API. One authorization implementation,
//  not two.
// =============================================================

/**
 * Populates $_SESSION with role/permissions and department-or-unit scope
 * for an already-verified account. No DB writes, no cookies — safe to call
 * on every request (web session bootstrap or API token resolution alike).
 *
 * @param array  $user       The account row, as returned by Account::toArray().
 * @param string $table      'users' | 'rotation_nurses' | 'clinical_students'
 * @param string $user_type  e.g. 'Admin', 'Rotation_Nurse', 'Clinical_Student'
 */
function hydrateRequestContext(mysqli $conn, PermissionManager $perm_manager, array $user, string $table, string $user_type): void
{
    // ── Common session variables ────────────────────────────────────────
    $_SESSION['logged_in']  = true;
    $_SESSION['user_id']    = $user['id'];
    $_SESSION['user_email'] = $user['email'];
    $_SESSION['firstname']  = $user['firstname'];
    $_SESSION['surname']    = $user['surname'];
    $_SESSION['fullname']   = $user['firstname'] . ' ' . $user['surname'];
    $_SESSION['usertype']   = $user_type;
    $_SESSION['profile']    = $user['profile'] ?? 'default.png';
    $_SESSION['user_table'] = $table;

    // ── Table-specific session setup ────────────────────────────────────
    if ($table === 'users') {
        // ── STAFF ────────────────────────────────────────────────────
        $_SESSION['role_id']  = $user['role_id']  ?? null;
        $_SESSION['username'] = $user['username'] ?? '';
        $_SESSION['grade']    = $user['grade']    ?? '';

        $user_permissions         = $perm_manager->getUserPermissions($user['id']);
        $user_role                = $perm_manager->getUserRole($user['id']);
        $_SESSION['role_name']    = $user_role['name']         ?? $user_type;
        $_SESSION['role_display'] = $user_role['display_name'] ?? $user_type;
        $_SESSION['permissions']  = array_column($user_permissions, 'name');

        $full_name = $user['firstname'] . ' ' . $user['surname'];

        // Preceptor → departments.preceptor column
        // Nurse_Manager → departments.nurse_manager column
        if (in_array($user_type, ['Preceptor', 'Nurse_Manager'], true)) {
            $col = ($user_type === 'Preceptor') ? 'preceptor' : 'nurse_manager';
            $ds  = $conn->prepare("
                SELECT id AS department_id, department_name
                FROM departments
                WHERE `{$col}` = ? AND status = 'Active'
                LIMIT 1
            ");
            $ds->bind_param('s', $full_name);
            $ds->execute();
            $dept = $ds->get_result()->fetch_assoc();
            $ds->close();
            if ($dept) {
                $_SESSION['department_id']   = (int)$dept['department_id'];
                $_SESSION['department_name'] = $dept['department_name'];
            }
        }

        // In_Charge → units.in_charge column (may manage multiple units)
        if ($user_type === 'In_Charge') {
            $us = $conn->prepare("
                SELECT id, unit_name FROM units
                WHERE in_charge = ? AND status = 'Active' AND cancelled_at IS NULL
            ");
            $us->bind_param('s', $full_name);
            $us->execute();
            $units_rows = $us->get_result()->fetch_all(MYSQLI_ASSOC);
            $us->close();
            if (!empty($units_rows)) {
                $_SESSION['unit_ids']   = array_column($units_rows, 'id');
                $_SESSION['unit_names'] = array_column($units_rows, 'unit_name');
            }
        }

    } elseif ($table === 'rotation_nurses') {
        // ── ROTATION NURSE ───────────────────────────────────────────
        $_SESSION['student_id']      = $user['student_id']      ?? '';
        $_SESSION['school_name']     = $user['school_name']     ?? '';
        $_SESSION['specialty_id']    = $user['specialty_id']    ?? null;
        $_SESSION['specialty_name']  = $user['specialty_name']  ?? '';
        $_SESSION['rotation_status'] = $user['rotation_status'] ?? 'Not_started';
        $_SESSION['role_name']       = 'Rotation Nurse';
        $_SESSION['role_display']    = 'Rotation Nurse';
        $_SESSION['permissions']     = [
            'view_own_schedule',
            'update_own_profile',
            'view_rotation_status',
        ];

    } elseif ($table === 'clinical_students') {
        // ── CLINICAL STUDENT ─────────────────────────────────────────
        $_SESSION['student_id']      = $user['student_id']      ?? '';
        $_SESSION['school_name']     = $user['school_name']     ?? '';
        $_SESSION['level']           = $user['level']           ?? '';
        $_SESSION['programme']       = $user['programme']       ?? '';
        $_SESSION['supervisor_name'] = $user['supervisor_name'] ?? '';
        $_SESSION['rotation_status'] = $user['rotation_status'] ?? 'Not_started';
        $_SESSION['role_name']       = 'Clinical Student';
        $_SESSION['role_display']    = 'Clinical Student';
        $_SESSION['permissions']     = [
            'view_own_schedule',
            'update_own_profile',
            'view_rotation_schedule',
        ];
    }
}

/**
 * @param array  $user       The account row, as returned by Account::toArray().
 * @param string $table      'users' | 'rotation_nurses' | 'clinical_students'
 * @param string $user_type  e.g. 'Admin', 'Rotation_Nurse', 'Clinical_Student'
 */
function establishUserSession(mysqli $conn, PermissionManager $perm_manager, array $user, string $table, string $user_type, bool $remember): void
{
    hydrateRequestContext($conn, $perm_manager, $user, $table, $user_type);

    // ── Last-login timestamp ────────────────────────────────────────────
    $upd = $conn->prepare("UPDATE `{$table}` SET last_login = NOW() WHERE id = ?");
    $upd->bind_param('i', $user['id']);
    $upd->execute();
    $upd->close();

    // ── Audit log (staff only) ──────────────────────────────────────────
    if ($table === 'users') {
        $perm_manager->logAudit(
            $user['id'], 'login', 'user', $user['id'], null,
            json_encode([
                'role'              => $_SESSION['role_name'],
                'permissions_count' => count($_SESSION['permissions']),
                'department_id'     => $_SESSION['department_id'] ?? null,
                'unit_ids'          => $_SESSION['unit_ids']      ?? [],
            ])
        );
    }

    // ── Remember-me cookie ───────────────────────────────────────────────
    if ($remember) {
        $token  = bin2hex(random_bytes(32));
        $expiry = time() + (30 * 24 * 60 * 60);
        $tok = $conn->prepare(
            "UPDATE `{$table}` SET remember_token = ?, token_expiry = FROM_UNIXTIME(?) WHERE id = ?"
        );
        $tok->bind_param('sii', $token, $expiry, $user['id']);
        $tok->execute();
        $tok->close();
        setcookie('remember_token', $token, $expiry, '/', '', true, true);
    }
}
