<?php
/**
 * @intranet-file common/user_preferences.php
 * @intranet-file-version 2026.05.05.1
 * @intranet-file-date 2026-05-05
 * @intranet-file-owner CSIF Intranet
 */
declare(strict_types=1);

require_once __DIR__ . '/db.php';

const INTRANET_THEME_MODE_DEFAULT = 'light';
const INTRANET_THEME_MODE_STORAGE_KEY = 'intranet_theme_mode';
const INTRANET_MENU_LAYOUT_DEFAULT = 'top';
const INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES = 30;
const INTRANET_SESSION_TIMEOUT_MIN_MINUTES = 15;
const INTRANET_SESSION_TIMEOUT_MAX_MINUTES = 60;
const INTRANET_HOME_FREQUENT_LIMIT_DEFAULT = 10;
const INTRANET_HOME_FREQUENT_LIMIT_MIN = 0;
const INTRANET_HOME_FREQUENT_LIMIT_MAX = 30;
const INTRANET_HOME_FREQUENT_APP_BG_DEFAULT = '#eaf8f0';
const INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT = '#eef5ff';

function intranet_theme_mode_options(): array
{
    return [
        'light' => 'Modo claro',
        'medium' => 'Modo medio',
        'dark' => 'Modo oscuro',
        'contrast' => 'Modo alto contraste',
    ];
}

function intranet_session_timeout_minute_options(): array
{
    $options = [];
    for ($minutes = INTRANET_SESSION_TIMEOUT_MIN_MINUTES; $minutes <= INTRANET_SESSION_TIMEOUT_MAX_MINUTES; $minutes += 5) {
        $options[$minutes] = $minutes . ' minutos';
    }

    return $options;
}

function intranet_menu_layout_options(): array
{
    return [
        'top' => 'Menu superior compacto',
        'dock' => 'Dock inferior',
        'sidebar' => 'Menu lateral clasico',
    ];
}

function intranet_session_timeout_normalize($minutes): int
{
    if (!is_numeric($minutes)) {
        return INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES;
    }

    $minutes = (int) $minutes;
    if ($minutes < INTRANET_SESSION_TIMEOUT_MIN_MINUTES) {
        return INTRANET_SESSION_TIMEOUT_MIN_MINUTES;
    }
    if ($minutes > INTRANET_SESSION_TIMEOUT_MAX_MINUTES) {
        return INTRANET_SESSION_TIMEOUT_MAX_MINUTES;
    }

    return $minutes;
}

function intranet_home_frequent_limit_normalize($limit): int
{
    if (!is_numeric($limit)) {
        return INTRANET_HOME_FREQUENT_LIMIT_DEFAULT;
    }

    $limit = (int) $limit;
    if ($limit < INTRANET_HOME_FREQUENT_LIMIT_MIN) {
        return INTRANET_HOME_FREQUENT_LIMIT_MIN;
    }
    if ($limit > INTRANET_HOME_FREQUENT_LIMIT_MAX) {
        return INTRANET_HOME_FREQUENT_LIMIT_MAX;
    }

    return $limit;
}

function intranet_color_hex_normalize($color, string $fallback): string
{
    $fallback = preg_match('/^#[0-9a-f]{6}$/i', $fallback) ? strtolower($fallback) : '#ffffff';
    $color = strtolower(trim((string) $color));
    if (preg_match('/^#[0-9a-f]{6}$/i', $color)) {
        return $color;
    }

    return $fallback;
}

function intranet_home_frequent_app_bg_normalize($color): string
{
    return intranet_color_hex_normalize($color, INTRANET_HOME_FREQUENT_APP_BG_DEFAULT);
}

function intranet_home_frequent_link_bg_normalize($color): string
{
    return intranet_color_hex_normalize($color, INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT);
}

function intranet_hex_contrast_text($color): string
{
    $color = intranet_color_hex_normalize($color, '#ffffff');
    $r = hexdec(substr($color, 1, 2));
    $g = hexdec(substr($color, 3, 2));
    $b = hexdec(substr($color, 5, 2));
    $brightness = (($r * 299) + ($g * 587) + ($b * 114)) / 1000;

    return $brightness < 140 ? '#ffffff' : '#1f2937';
}

function intranet_session_timeout_label($minutes): string
{
    $minutes = intranet_session_timeout_normalize($minutes);
    return $minutes . ' minutos';
}

function intranet_home_frequent_limit_label($limit): string
{
    $limit = intranet_home_frequent_limit_normalize($limit);
    if ($limit === 0) {
        return 'Oculto';
    }

    return $limit . ' accesos';
}

function intranet_menu_layout_normalize(?string $layout): string
{
    $layout = strtolower(trim((string) $layout));
    $aliases = [
        'top' => 'top',
        'superior' => 'top',
        'menu-superior' => 'top',
        'header' => 'top',
        'dock' => 'dock',
        'inferior' => 'dock',
        'bottom' => 'dock',
        'menu-inferior' => 'dock',
        'sidebar' => 'sidebar',
        'lateral' => 'sidebar',
        'classic' => 'sidebar',
        'clasico' => 'sidebar',
    ];

    return $aliases[$layout] ?? INTRANET_MENU_LAYOUT_DEFAULT;
}

function intranet_menu_layout_label(?string $layout): string
{
    $layout = intranet_menu_layout_normalize($layout);
    $options = intranet_menu_layout_options();
    return $options[$layout] ?? $options[INTRANET_MENU_LAYOUT_DEFAULT];
}

function intranet_theme_mode_normalize(?string $mode): string
{
    $mode = strtolower(trim((string) $mode));
    $aliases = [
        'light' => 'light',
        'claro' => 'light',
        'medium' => 'medium',
        'medio' => 'medium',
        'midlight' => 'medium',
        'medium-light' => 'medium',
        'medio-claro' => 'medium',
        'dark' => 'dark',
        'oscuro' => 'dark',
        'middark' => 'dark',
        'medium-dark' => 'dark',
        'medio-oscuro' => 'dark',
        'contrast' => 'contrast',
        'high-contrast' => 'contrast',
        'highcontrast' => 'contrast',
        'alto-contraste' => 'contrast',
        'alto contraste' => 'contrast',
    ];

    return $aliases[$mode] ?? INTRANET_THEME_MODE_DEFAULT;
}

function intranet_theme_mode_is_dark(?string $mode): bool
{
    $mode = intranet_theme_mode_normalize($mode);
    return $mode === 'dark' || $mode === 'contrast';
}

function intranet_theme_mode_label(?string $mode): string
{
    $mode = intranet_theme_mode_normalize($mode);
    $options = intranet_theme_mode_options();
    return $options[$mode] ?? $options[INTRANET_THEME_MODE_DEFAULT];
}

function intranet_theme_mode_family(?string $mode): string
{
    return intranet_theme_mode_is_dark($mode) ? 'dark' : 'light';
}

function intranet_user_preferences_ensure_table(PDO $pdo): void
{
    static $done = false;
    if ($done) {
        return;
    }

    $pdo->exec(
        "CREATE TABLE IF NOT EXISTS intranet_user_preferences (
            username varchar(100) NOT NULL,
            theme_mode varchar(10) NOT NULL DEFAULT 'light',
            menu_layout varchar(20) NOT NULL DEFAULT 'top',
            session_timeout_minutes int unsigned NOT NULL DEFAULT 30,
            home_frequent_limit int unsigned NOT NULL DEFAULT 10,
            home_frequent_app_bg varchar(7) NOT NULL DEFAULT '#eaf8f0',
            home_frequent_link_bg varchar(7) NOT NULL DEFAULT '#eef5ff',
            created_at timestamp NULL DEFAULT current_timestamp(),
            updated_at timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
            PRIMARY KEY (username)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci"
    );

    $columnCheck = $pdo->query("SHOW COLUMNS FROM intranet_user_preferences LIKE 'session_timeout_minutes'");
    $hasSessionTimeoutColumn = $columnCheck !== false && $columnCheck->fetch(PDO::FETCH_ASSOC);
    if (!$hasSessionTimeoutColumn) {
        $pdo->exec(
            "ALTER TABLE intranet_user_preferences
             ADD COLUMN session_timeout_minutes int unsigned NOT NULL DEFAULT 30 AFTER theme_mode"
        );
    }

    $columnCheck = $pdo->query("SHOW COLUMNS FROM intranet_user_preferences LIKE 'menu_layout'");
    $hasMenuLayoutColumn = $columnCheck !== false && $columnCheck->fetch(PDO::FETCH_ASSOC);
    if (!$hasMenuLayoutColumn) {
        $pdo->exec(
            "ALTER TABLE intranet_user_preferences
             ADD COLUMN menu_layout varchar(20) NOT NULL DEFAULT 'top' AFTER theme_mode"
        );
    }

    $columnCheck = $pdo->query("SHOW COLUMNS FROM intranet_user_preferences LIKE 'home_frequent_limit'");
    $hasHomeFrequentLimitColumn = $columnCheck !== false && $columnCheck->fetch(PDO::FETCH_ASSOC);
    if (!$hasHomeFrequentLimitColumn) {
        $pdo->exec(
            "ALTER TABLE intranet_user_preferences
             ADD COLUMN home_frequent_limit int unsigned NOT NULL DEFAULT 10 AFTER session_timeout_minutes"
        );
    }

    $columnCheck = $pdo->query("SHOW COLUMNS FROM intranet_user_preferences LIKE 'home_frequent_app_bg'");
    $hasHomeFrequentAppBgColumn = $columnCheck !== false && $columnCheck->fetch(PDO::FETCH_ASSOC);
    if (!$hasHomeFrequentAppBgColumn) {
        $pdo->exec(
            "ALTER TABLE intranet_user_preferences
             ADD COLUMN home_frequent_app_bg varchar(7) NOT NULL DEFAULT '#eaf8f0' AFTER home_frequent_limit"
        );
    }

    $columnCheck = $pdo->query("SHOW COLUMNS FROM intranet_user_preferences LIKE 'home_frequent_link_bg'");
    $hasHomeFrequentLinkBgColumn = $columnCheck !== false && $columnCheck->fetch(PDO::FETCH_ASSOC);
    if (!$hasHomeFrequentLinkBgColumn) {
        $pdo->exec(
            "ALTER TABLE intranet_user_preferences
             ADD COLUMN home_frequent_link_bg varchar(7) NOT NULL DEFAULT '#eef5ff' AFTER home_frequent_app_bg"
        );
    }

    $done = true;
}

function intranet_user_theme_mode(PDO $pdo, string $username, string $fallback = INTRANET_THEME_MODE_DEFAULT): string
{
    $username = trim($username);
    if ($username === '') {
        return intranet_theme_mode_normalize($fallback);
    }

    intranet_user_preferences_ensure_table($pdo);
    $st = $pdo->prepare("SELECT theme_mode FROM intranet_user_preferences WHERE username = ? LIMIT 1");
    $st->execute([$username]);
    $value = $st->fetchColumn();

    if ($value === false || $value === null) {
        return intranet_theme_mode_normalize($fallback);
    }

    return intranet_theme_mode_normalize((string) $value);
}

function intranet_set_user_theme_mode(PDO $pdo, string $username, string $mode): string
{
    $username = trim($username);
    $mode = intranet_theme_mode_normalize($mode);

    if ($username === '') {
        return $mode;
    }

    intranet_user_preferences_ensure_table($pdo);
    $sql = "INSERT INTO intranet_user_preferences (username, theme_mode)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE theme_mode = VALUES(theme_mode), updated_at = CURRENT_TIMESTAMP()";
    $st = $pdo->prepare($sql);
    $st->execute([$username, $mode]);

    return $mode;
}

function intranet_user_menu_layout(PDO $pdo, string $username, string $fallback = INTRANET_MENU_LAYOUT_DEFAULT): string
{
    $username = trim($username);
    if ($username === '') {
        return intranet_menu_layout_normalize($fallback);
    }

    intranet_user_preferences_ensure_table($pdo);
    $st = $pdo->prepare("SELECT menu_layout FROM intranet_user_preferences WHERE username = ? LIMIT 1");
    $st->execute([$username]);
    $value = $st->fetchColumn();

    if ($value === false || $value === null) {
        return intranet_menu_layout_normalize($fallback);
    }

    return intranet_menu_layout_normalize((string) $value);
}

function intranet_set_user_menu_layout(PDO $pdo, string $username, string $layout): string
{
    $username = trim($username);
    $layout = intranet_menu_layout_normalize($layout);

    if ($username === '') {
        return $layout;
    }

    intranet_user_preferences_ensure_table($pdo);
    $sql = "INSERT INTO intranet_user_preferences (username, menu_layout)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE menu_layout = VALUES(menu_layout), updated_at = CURRENT_TIMESTAMP()";
    $st = $pdo->prepare($sql);
    $st->execute([$username, $layout]);

    return $layout;
}

function intranet_user_session_timeout_minutes(
    PDO $pdo,
    string $username,
    int $fallback = INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES
): int {
    $username = trim($username);
    if ($username === '') {
        return intranet_session_timeout_normalize($fallback);
    }

    intranet_user_preferences_ensure_table($pdo);
    $st = $pdo->prepare("SELECT session_timeout_minutes FROM intranet_user_preferences WHERE username = ? LIMIT 1");
    $st->execute([$username]);
    $value = $st->fetchColumn();

    if ($value === false || $value === null) {
        return intranet_session_timeout_normalize($fallback);
    }

    return intranet_session_timeout_normalize($value);
}

function intranet_set_user_session_timeout_minutes(PDO $pdo, string $username, $minutes): int
{
    $username = trim($username);
    $minutes = intranet_session_timeout_normalize($minutes);

    if ($username === '') {
        return $minutes;
    }

    intranet_user_preferences_ensure_table($pdo);
    $sql = "INSERT INTO intranet_user_preferences (username, session_timeout_minutes)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE session_timeout_minutes = VALUES(session_timeout_minutes), updated_at = CURRENT_TIMESTAMP()";
    $st = $pdo->prepare($sql);
    $st->execute([$username, $minutes]);

    return $minutes;
}

function intranet_user_home_frequent_limit(
    PDO $pdo,
    string $username,
    int $fallback = INTRANET_HOME_FREQUENT_LIMIT_DEFAULT
): int {
    $username = trim($username);
    if ($username === '') {
        return intranet_home_frequent_limit_normalize($fallback);
    }

    intranet_user_preferences_ensure_table($pdo);
    $st = $pdo->prepare("SELECT home_frequent_limit FROM intranet_user_preferences WHERE username = ? LIMIT 1");
    $st->execute([$username]);
    $value = $st->fetchColumn();

    if ($value === false || $value === null) {
        return intranet_home_frequent_limit_normalize($fallback);
    }

    return intranet_home_frequent_limit_normalize($value);
}

function intranet_set_user_home_frequent_limit(PDO $pdo, string $username, $limit): int
{
    $username = trim($username);
    $limit = intranet_home_frequent_limit_normalize($limit);

    if ($username === '') {
        return $limit;
    }

    intranet_user_preferences_ensure_table($pdo);
    $sql = "INSERT INTO intranet_user_preferences (username, home_frequent_limit)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE home_frequent_limit = VALUES(home_frequent_limit), updated_at = CURRENT_TIMESTAMP()";
    $st = $pdo->prepare($sql);
    $st->execute([$username, $limit]);

    return $limit;
}

function intranet_user_home_frequent_app_bg(
    PDO $pdo,
    string $username,
    string $fallback = INTRANET_HOME_FREQUENT_APP_BG_DEFAULT
): string {
    $username = trim($username);
    if ($username === '') {
        return intranet_home_frequent_app_bg_normalize($fallback);
    }

    intranet_user_preferences_ensure_table($pdo);
    $st = $pdo->prepare("SELECT home_frequent_app_bg FROM intranet_user_preferences WHERE username = ? LIMIT 1");
    $st->execute([$username]);
    $value = $st->fetchColumn();

    if ($value === false || $value === null) {
        return intranet_home_frequent_app_bg_normalize($fallback);
    }

    return intranet_home_frequent_app_bg_normalize($value);
}

function intranet_set_user_home_frequent_app_bg(PDO $pdo, string $username, $color): string
{
    $username = trim($username);
    $color = intranet_home_frequent_app_bg_normalize($color);

    if ($username === '') {
        return $color;
    }

    intranet_user_preferences_ensure_table($pdo);
    $sql = "INSERT INTO intranet_user_preferences (username, home_frequent_app_bg)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE home_frequent_app_bg = VALUES(home_frequent_app_bg), updated_at = CURRENT_TIMESTAMP()";
    $st = $pdo->prepare($sql);
    $st->execute([$username, $color]);

    return $color;
}

function intranet_user_home_frequent_link_bg(
    PDO $pdo,
    string $username,
    string $fallback = INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT
): string {
    $username = trim($username);
    if ($username === '') {
        return intranet_home_frequent_link_bg_normalize($fallback);
    }

    intranet_user_preferences_ensure_table($pdo);
    $st = $pdo->prepare("SELECT home_frequent_link_bg FROM intranet_user_preferences WHERE username = ? LIMIT 1");
    $st->execute([$username]);
    $value = $st->fetchColumn();

    if ($value === false || $value === null) {
        return intranet_home_frequent_link_bg_normalize($fallback);
    }

    return intranet_home_frequent_link_bg_normalize($value);
}

function intranet_set_user_home_frequent_link_bg(PDO $pdo, string $username, $color): string
{
    $username = trim($username);
    $color = intranet_home_frequent_link_bg_normalize($color);

    if ($username === '') {
        return $color;
    }

    intranet_user_preferences_ensure_table($pdo);
    $sql = "INSERT INTO intranet_user_preferences (username, home_frequent_link_bg)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE home_frequent_link_bg = VALUES(home_frequent_link_bg), updated_at = CURRENT_TIMESTAMP()";
    $st = $pdo->prepare($sql);
    $st->execute([$username, $color]);

    return $color;
}

function intranet_load_session_theme_mode(?PDO $pdo = null): string
{
    if (isset($_SESSION['theme_mode'])) {
        $_SESSION['theme_mode'] = intranet_theme_mode_normalize((string) $_SESSION['theme_mode']);
        return (string) $_SESSION['theme_mode'];
    }

    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        $_SESSION['theme_mode'] = INTRANET_THEME_MODE_DEFAULT;
        return INTRANET_THEME_MODE_DEFAULT;
    }

    try {
        $pdo = $pdo ?? db();
        $mode = intranet_user_theme_mode($pdo, $username, INTRANET_THEME_MODE_DEFAULT);
    } catch (Throwable $e) {
        $mode = INTRANET_THEME_MODE_DEFAULT;
    }

    $_SESSION['theme_mode'] = $mode;
    return $mode;
}

function intranet_set_session_theme_mode(string $mode): string
{
    $mode = intranet_theme_mode_normalize($mode);
    $_SESSION['theme_mode'] = $mode;
    return $mode;
}

function intranet_load_session_timeout_minutes(?PDO $pdo = null): int
{
    if (isset($_SESSION['session_timeout_minutes'])) {
        $_SESSION['session_timeout_minutes'] = intranet_session_timeout_normalize($_SESSION['session_timeout_minutes']);
        return (int) $_SESSION['session_timeout_minutes'];
    }

    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        $_SESSION['session_timeout_minutes'] = INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES;
        return INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES;
    }

    try {
        $pdo = $pdo ?? db();
        $minutes = intranet_user_session_timeout_minutes($pdo, $username, INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES);
    } catch (Throwable $e) {
        $minutes = INTRANET_SESSION_TIMEOUT_DEFAULT_MINUTES;
    }

    $_SESSION['session_timeout_minutes'] = $minutes;
    return $minutes;
}

function intranet_set_session_timeout_minutes($minutes): int
{
    $minutes = intranet_session_timeout_normalize($minutes);
    $_SESSION['session_timeout_minutes'] = $minutes;
    return $minutes;
}

function intranet_load_session_home_frequent_limit(?PDO $pdo = null): int
{
    if (isset($_SESSION['home_frequent_limit'])) {
        $_SESSION['home_frequent_limit'] = intranet_home_frequent_limit_normalize($_SESSION['home_frequent_limit']);
        return (int) $_SESSION['home_frequent_limit'];
    }

    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        $_SESSION['home_frequent_limit'] = INTRANET_HOME_FREQUENT_LIMIT_DEFAULT;
        return INTRANET_HOME_FREQUENT_LIMIT_DEFAULT;
    }

    try {
        $pdo = $pdo ?? db();
        $limit = intranet_user_home_frequent_limit($pdo, $username, INTRANET_HOME_FREQUENT_LIMIT_DEFAULT);
    } catch (Throwable $e) {
        $limit = INTRANET_HOME_FREQUENT_LIMIT_DEFAULT;
    }

    $_SESSION['home_frequent_limit'] = $limit;
    return $limit;
}

function intranet_set_session_home_frequent_limit($limit): int
{
    $limit = intranet_home_frequent_limit_normalize($limit);
    $_SESSION['home_frequent_limit'] = $limit;
    return $limit;
}

function intranet_load_session_home_frequent_app_bg(?PDO $pdo = null): string
{
    if (isset($_SESSION['home_frequent_app_bg'])) {
        $_SESSION['home_frequent_app_bg'] = intranet_home_frequent_app_bg_normalize($_SESSION['home_frequent_app_bg']);
        return (string) $_SESSION['home_frequent_app_bg'];
    }

    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        $_SESSION['home_frequent_app_bg'] = INTRANET_HOME_FREQUENT_APP_BG_DEFAULT;
        return INTRANET_HOME_FREQUENT_APP_BG_DEFAULT;
    }

    try {
        $pdo = $pdo ?? db();
        $color = intranet_user_home_frequent_app_bg($pdo, $username, INTRANET_HOME_FREQUENT_APP_BG_DEFAULT);
    } catch (Throwable $e) {
        $color = INTRANET_HOME_FREQUENT_APP_BG_DEFAULT;
    }

    $_SESSION['home_frequent_app_bg'] = $color;
    return $color;
}

function intranet_set_session_home_frequent_app_bg($color): string
{
    $color = intranet_home_frequent_app_bg_normalize($color);
    $_SESSION['home_frequent_app_bg'] = $color;
    return $color;
}

function intranet_load_session_home_frequent_link_bg(?PDO $pdo = null): string
{
    if (isset($_SESSION['home_frequent_link_bg'])) {
        $_SESSION['home_frequent_link_bg'] = intranet_home_frequent_link_bg_normalize($_SESSION['home_frequent_link_bg']);
        return (string) $_SESSION['home_frequent_link_bg'];
    }

    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        $_SESSION['home_frequent_link_bg'] = INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT;
        return INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT;
    }

    try {
        $pdo = $pdo ?? db();
        $color = intranet_user_home_frequent_link_bg($pdo, $username, INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT);
    } catch (Throwable $e) {
        $color = INTRANET_HOME_FREQUENT_LINK_BG_DEFAULT;
    }

    $_SESSION['home_frequent_link_bg'] = $color;
    return $color;
}

function intranet_set_session_home_frequent_link_bg($color): string
{
    $color = intranet_home_frequent_link_bg_normalize($color);
    $_SESSION['home_frequent_link_bg'] = $color;
    return $color;
}

function intranet_load_session_menu_layout(?PDO $pdo = null): string
{
    if (isset($_SESSION['menu_layout'])) {
        $_SESSION['menu_layout'] = intranet_menu_layout_normalize((string) $_SESSION['menu_layout']);
        return (string) $_SESSION['menu_layout'];
    }

    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        $_SESSION['menu_layout'] = INTRANET_MENU_LAYOUT_DEFAULT;
        return INTRANET_MENU_LAYOUT_DEFAULT;
    }

    try {
        $pdo = $pdo ?? db();
        $layout = intranet_user_menu_layout($pdo, $username, INTRANET_MENU_LAYOUT_DEFAULT);
    } catch (Throwable $e) {
        $layout = INTRANET_MENU_LAYOUT_DEFAULT;
    }

    $_SESSION['menu_layout'] = $layout;
    return $layout;
}

function intranet_set_session_menu_layout(string $layout): string
{
    $layout = intranet_menu_layout_normalize($layout);
    $_SESSION['menu_layout'] = $layout;
    return $layout;
}

function intranet_touch_session_activity(?int $now = null): void
{
    if (!isset($_SESSION['username'])) {
        return;
    }

    $_SESSION['last_activity_at'] = $now ?? time();
}

function intranet_destroy_current_session(): void
{
    $_SESSION = [];

    if (session_status() !== PHP_SESSION_ACTIVE) {
        return;
    }

    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();
        setcookie(
            session_name(),
            '',
            time() - 42000,
            $params['path'] ?? '/',
            $params['domain'] ?? '',
            (bool) ($params['secure'] ?? false),
            (bool) ($params['httponly'] ?? false)
        );
    }

    session_destroy();
}

function intranet_enforce_session_timeout(?PDO $pdo = null): bool
{
    $username = trim((string) ($_SESSION['username'] ?? ''));
    if ($username === '') {
        return true;
    }

    $timeoutMinutes = intranet_load_session_timeout_minutes($pdo);
    $lastActivityAt = isset($_SESSION['last_activity_at']) ? (int) $_SESSION['last_activity_at'] : 0;
    $now = time();

    if ($lastActivityAt > 0 && ($now - $lastActivityAt) >= ($timeoutMinutes * 60)) {
        intranet_destroy_current_session();
        return false;
    }

    intranet_touch_session_activity($now);
    return true;
}

function intranet_theme_html_attr(?string $mode = null): string
{
    $mode = intranet_theme_mode_normalize($mode ?? (string) ($_SESSION['theme_mode'] ?? INTRANET_THEME_MODE_DEFAULT));
    $family = intranet_theme_mode_family($mode);
    return 'data-theme="' . htmlspecialchars($family, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
        . '" data-theme-variant="' . htmlspecialchars($mode, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '"';
}

function intranet_theme_bootstrap_script_tag(?string $mode = null): string
{
    $mode = intranet_theme_mode_normalize($mode ?? (string) ($_SESSION['theme_mode'] ?? INTRANET_THEME_MODE_DEFAULT));
    $storageKey = INTRANET_THEME_MODE_STORAGE_KEY;
    $allowClientSaved = empty($_SESSION['username']);
    $modes = array_keys(intranet_theme_mode_options());

    $modeJson = json_encode($mode, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $storageJson = json_encode($storageKey, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $allowClientSavedJson = $allowClientSaved ? 'true' : 'false';
    $aliasesJson = json_encode([
        'light' => 'light',
        'claro' => 'light',
        'medium' => 'medium',
        'medio' => 'medium',
        'midlight' => 'medium',
        'medium-light' => 'medium',
        'medio-claro' => 'medium',
        'dark' => 'dark',
        'oscuro' => 'dark',
        'middark' => 'dark',
        'medium-dark' => 'dark',
        'medio-oscuro' => 'dark',
        'contrast' => 'contrast',
        'high-contrast' => 'contrast',
        'highcontrast' => 'contrast',
        'alto-contraste' => 'contrast',
        'alto contraste' => 'contrast',
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    return "<script>(function(){"
        . "var fallback={$modeJson};"
        . "var key={$storageJson};"
        . "var allowClientSaved={$allowClientSavedJson};"
        . "var aliasMap={$aliasesJson};"
        . "function normalizeMode(value){value=String(value||'').toLowerCase().trim();return aliasMap[value]||'light';}"
        . "function isDarkMode(value){return value==='dark'||value==='contrast';}"
        . "function themeFamily(value){return isDarkMode(value)?'dark':'light';}"
        . "function canShowAppVersion(){var path=String((window.location&&window.location.pathname)||'');return /\\/(?:apps|plugins)\\//.test(path)&&!/\\/(?:api|install)\\//.test(path);}"
        . "function findVersionTargets(doc){var selectors=['.header-top .header-titles h2','.header-top .header-titles h1','.header-top .header-info h2','.header-top .header-info h1','.header-top > div > h2','.header-top > div > h1','.header-intranet-top .header-info h2','.header-intranet-top .header-info h1','.header-intranet-top .header-left h2','.header-intranet-top .header-left h1','.header-intranet-top > div > h2','.header-intranet-top > div > h1','.iban-header-copy h2','.iban-header-copy h1','.app-header-copy h2','.app-header-copy h1','.gf-title h1','.gf-title h2','.head h1','.head h2'];var seen=[];var out=[];for(var i=0;i<selectors.length;i++){var nodes=doc.querySelectorAll(selectors[i]);for(var j=0;j<nodes.length;j++){var node=nodes[j];if(seen.indexOf(node)!==-1){continue;}seen.push(node);out.push(node);}}return out;}"
        . "function injectAppVersionBadge(doc,version){version=String(version||'').trim();if(!version){return;}var targets=findVersionTargets(doc);for(var i=0;i<targets.length;i++){var title=targets[i];var row=(title.parentElement&&title.parentElement.classList&&title.parentElement.classList.contains('app-title-row'))?title.parentElement:null;if(!row){row=doc.createElement('div');row.className='app-title-row';title.parentNode.insertBefore(row,title);row.appendChild(title);}if(row.querySelector('.app-version-badge')){continue;}var badge=doc.createElement('span');badge.className='app-version-badge';badge.textContent='v'+version;row.appendChild(badge);}}"
        . "function loadAppVersion(doc){if(!canShowAppVersion()||!window.fetch){return;}var url;try{url=new URL('app.json',window.location.href);}catch(e){return;}window.fetch(url.toString(),{credentials:'same-origin',cache:'no-store'}).then(function(resp){if(!resp.ok){throw new Error('app.json');}return resp.json();}).then(function(meta){injectAppVersionBadge(doc,meta&&meta.version?meta.version:'');}).catch(function(){});}"
        . "var mode=normalizeMode(fallback);"
        . "try{if(allowClientSaved){var saved=window.localStorage.getItem(key);mode=normalizeMode(saved||mode);}window.localStorage.setItem(key,mode);}catch(e){}"
        . "function applyTheme(doc){if(!doc||!doc.documentElement){return;}var family=themeFamily(mode);doc.documentElement.setAttribute('data-theme',family);doc.documentElement.setAttribute('data-theme-variant',mode);doc.documentElement.style.colorScheme=(family==='dark'?'dark':'light');if(doc.body){doc.body.setAttribute('data-theme',family);doc.body.setAttribute('data-theme-variant',mode);}try{var frames=doc.querySelectorAll('iframe');for(var i=0;i<frames.length;i++){var frame=frames[i];if(frame&&frame.contentWindow&&frame.contentWindow.document){applyTheme(frame.contentWindow.document);}}}catch(e){}}"
        . "applyTheme(document);"
        . "document.addEventListener('DOMContentLoaded',function(){applyTheme(document);loadAppVersion(document);});"
        . "window.intranetApplyThemeMode=function(nextMode){mode=normalizeMode(nextMode);try{window.localStorage.setItem(key,mode);}catch(e){}applyTheme(document);try{if(window.top&&window.top!==window){applyTheme(window.top.document);window.top.localStorage.setItem(key,mode);}}catch(e){}};"
        . "})();</script>";
}

function intranet_preferences_ensure_app_registered(PDO $pdo): void
{
    intranet_user_preferences_ensure_table($pdo);

    $appId = 'preferences';
    $name = 'Preferencias';
    $url = 'base/preferences/index.php';
    $group = 'Generales';
    $description = 'Preferencias personales de interfaz';
    $icon = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0A1.65 1.65 0 0 0 10 3.09V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0A1.65 1.65 0 0 0 20.91 10H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>';
    $roles = json_encode(['app_users'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    $st = $pdo->prepare("SELECT id FROM intranet_apps WHERE app_id = ? LIMIT 1");
    $st->execute([$appId]);
    $row = $st->fetch(PDO::FETCH_ASSOC);

    if ($row) {
        return;
    }

    $pos = 1;
    try {
        $p = $pdo->prepare("SELECT COALESCE(MAX(position), 0) + 1 FROM intranet_apps WHERE group_name = ?");
        $p->execute([$group]);
        $pos = (int) ($p->fetchColumn() ?: 1);
    } catch (Throwable $e) {
        $pos = 1;
    }

    $ins = $pdo->prepare("INSERT INTO intranet_apps (app_id, name, url, group_name, description, icon, image, new_tab, roles_json, position, is_enabled, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, NULL, 0, ?, ?, 1, NOW(), NOW())");
    $ins->execute([$appId, $name, $url, $group, $description, $icon, $roles, $pos]);
}
