<?php
// ============================================================
// Helper Functions
// ============================================================

require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../config/database.php';

// ─── Session ────────────────────────────────────────────────
function startSession(): void {
    if (session_status() === PHP_SESSION_NONE) {
        session_set_cookie_params(['httponly' => true, 'samesite' => 'Strict']);
        session_start();
    }
}

function isLoggedIn(): bool {
    startSession();
    return isset($_SESSION['user_id']);
}

function requireLogin(): void {
    if (!isLoggedIn()) {
        header('Location: ' . APP_URL . '/index.php?page=login');
        exit;
    }
}

function requireRole(array $roles): void {
    requireLogin();
    if (!in_array($_SESSION['role'], $roles)) {
        header('Location: ' . APP_URL . '/index.php?page=dashboard&error=unauthorized');
        exit;
    }
}

function currentUser(): ?array {
    startSession();
    if (!isset($_SESSION['user_id'])) return null;
    $db   = Database::getInstance();
    $stmt = $db->prepare('SELECT * FROM users WHERE user_id = ?');
    $stmt->execute([$_SESSION['user_id']]);
    return $stmt->fetch() ?: null;
}

// ─── Activity Logging ────────────────────────────────────────
function logActivity(string $action, string $module, string $description = '', ?int $recordId = null): void {
    startSession();
    $db   = Database::getInstance();
    $stmt = $db->prepare('
        INSERT INTO activity_logs (user_id, user_role, action, module, description, record_id, ip_address, user_agent)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    ');
    $stmt->execute([
        $_SESSION['user_id']   ?? null,
        $_SESSION['role']      ?? null,
        $action,
        $module,
        $description,
        $recordId,
        $_SERVER['REMOTE_ADDR']    ?? '',
        $_SERVER['HTTP_USER_AGENT'] ?? '',
    ]);
}

// ─── CSRF ────────────────────────────────────────────────────
function csrfToken(): string {
    startSession();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

function verifyCsrf(): void {
    startSession();
    $token = $_POST['csrf_token'] ?? '';
    if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
        http_response_code(403);
        die('CSRF token mismatch.');
    }
}

// ─── OTP ─────────────────────────────────────────────────────
function generateOTP(): string {
    return str_pad((string)random_int(0, 999999), 6, '0', STR_PAD_LEFT);
}

function storeOTP(int $userId, string $otp): void {
    $db      = Database::getInstance();
    $expires = date('Y-m-d H:i:s', strtotime('+' . OTP_EXPIRY_MINUTES . ' minutes'));
    $hashed  = password_hash($otp, PASSWORD_BCRYPT);
    $db->prepare('UPDATE users SET encryption_code = ?, otp_expires_at = ? WHERE user_id = ?')
       ->execute([$hashed, $expires, $userId]);
}

function verifyOTP(int $userId, string $otp): bool {
    $db   = Database::getInstance();
    $stmt = $db->prepare('SELECT encryption_code, otp_expires_at FROM users WHERE user_id = ?');
    $stmt->execute([$userId]);
    $row = $stmt->fetch();
    if (!$row) return false;
    if (new DateTime() > new DateTime($row['otp_expires_at'])) return false;
    return password_verify($otp, $row['encryption_code']);
}

// ─── Certificate Number Generator ────────────────────────────
function generateCertNumber(string $labCode): string {
    $db   = Database::getInstance();
    $year = date('Y');
    $stmt = $db->prepare('SELECT COUNT(*) FROM certificates WHERE YEAR(date_created) = ?');
    $stmt->execute([$year]);
    $count = (int)$stmt->fetchColumn() + 1;
    return sprintf('GSA/%s/%s/%04d', $labCode, $year, $count);
}

function generateRequestNumber(): string {
    $db    = Database::getInstance();
    $year  = date('Y');
    $month = date('m');
    $stmt  = $db->prepare('SELECT COUNT(*) FROM requests WHERE YEAR(date_created) = ? AND MONTH(date_created) = ?');
    $stmt->execute([$year, $month]);
    $count = (int)$stmt->fetchColumn() + 1;
    return sprintf('REQ-%s%s-%04d', $year, $month, $count);
}

// ─── Flash Messages ───────────────────────────────────────────
function setFlash(string $type, string $message): void {
    startSession();
    $_SESSION['flash'] = ['type' => $type, 'message' => $message];
}

function getFlash(): ?array {
    startSession();
    $flash = $_SESSION['flash'] ?? null;
    unset($_SESSION['flash']);
    return $flash;
}

// ─── Input sanitization ───────────────────────────────────────
function sanitize(string $value): string {
    return htmlspecialchars(strip_tags(trim($value)), ENT_QUOTES, 'UTF-8');
}

function e(string $value): string {
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}

// ─── Lab Access Check ─────────────────────────────────────────
function userCanAccessLab(int $userId, int $labId): bool {
    $db   = Database::getInstance();
    // Admin can access all
    $stmt = $db->prepare('SELECT role FROM users WHERE user_id = ?');
    $stmt->execute([$userId]);
    $user = $stmt->fetch();
    if ($user && $user['role'] === 'admin') return true;

    $stmt = $db->prepare('SELECT 1 FROM user_lab_assignments WHERE user_id = ? AND lab_id = ?');
    $stmt->execute([$userId, $labId]);
    return (bool)$stmt->fetch();
}

function getUserLabs(int $userId): array {
    $db = Database::getInstance();
    // Admin sees all
    $stmt = $db->prepare('SELECT role FROM users WHERE user_id = ?');
    $stmt->execute([$userId]);
    $user = $stmt->fetch();
    if ($user && $user['role'] === 'admin') {
        return $db->query('SELECT * FROM laboratories ORDER BY lab_name')->fetchAll();
    }
    $stmt = $db->prepare('
        SELECT l.* FROM laboratories l
        JOIN user_lab_assignments a ON l.lab_id = a.lab_id
        WHERE a.user_id = ?
        ORDER BY l.lab_name
    ');
    $stmt->execute([$userId]);
    return $stmt->fetchAll();
}
