<?php
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/functions.php';

// Cabeçalhos de segurança HTTP (todas as rotas deste arquivo)
if (!headers_sent()) {
    header('X-Frame-Options: SAMEORIGIN');
    header('X-Content-Type-Options: nosniff');
    header('X-XSS-Protection: 1; mode=block');
    header('Referrer-Policy: strict-origin-when-cross-origin');
    header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://fonts.gstatic.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self'; frame-ancestors 'self';");
}

// CLI cron
if (php_sapi_name() === 'cli' && isset($argv[1]) && $argv[1] === 'cron') {
    require __DIR__ . '/ping_cron.php';
    exit;
}

// HTTP cron
if (isset($_GET['cron']) && $_GET['cron'] == '1') {
    $pdo = db();
    // Limite de bruteforce cron token: max 10 erros em 5 minutos (300s)
    if (!empty(CRON_HTTP_TOKEN) && ($_GET['cron_token'] ?? '') !== CRON_HTTP_TOKEN) {
        if (!check_rate_limit_ip($pdo, 'cron_token', 10, 300)) {
            http_response_code(429);
            echo "Accesso bloqueado temporariamente pelo Anti-Brute-Force.";
            exit;
        }
        http_response_code(403);
        echo "Token invalido.";
        exit;
    }
    // Sucesso, libera IP se estivesse bloqueado
    clear_rate_limit_ip($pdo, 'cron_token');
    
    require __DIR__ . '/ping_cron.php';
    exit;
}

$page = $_GET['page'] ?? 'home';

// Página de ativação de licença (acessível apenas logado)
if ($page === 'license_activate') {
    require_session_only();
    @unlink('/opt/monitorping/.license_key');
    @unlink('/opt/monitorping/.license_cache');
    require __DIR__ . '/includes/license_activate_page.php';
    exit;
}

if ($page === 'license_recheck') {
    require_session_only();
    // Limpa cache e recheca agora
    @unlink('/opt/monitorping/.license_cache');
    $lic = license_check();
    if (in_array($lic['status'], ['ok', 'warning', 'offline_warning'])) {
        $_SESSION['license_status']  = $lic['status'];
        $_SESSION['license_message'] = $lic['message'] ?? '';
        header('Location: ' . BASE_URL . 'index.php?page=dashboard');
    } else {
        header('Location: ' . BASE_URL . 'index.php?page=dashboard&recheck_fail=1');
    }
    exit;
}

if ($page === 'login') {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $email = trim($_POST['email'] ?? '');
        $password = $_POST['password'] ?? '';
        
        $pdo = db();
        // Limite de login: max 5 tentativas erradas em 10 minutos (600s)
        if (!check_rate_limit_ip($pdo, 'login_attempt', 5, 600)) {
            $error = "Muitas tentativas falhas. Bloqueado por medida de segurança. Tente novamente em alguns minutos.";
        } else {
            $loginResult = login($email, $password);
            if ($loginResult === '2fa') {
                clear_rate_limit_ip($pdo, 'login_attempt');
                redirect('index.php?page=verify_2fa');
            } elseif ($loginResult === 'unverified') {
                $error = 'Confirme seu e-mail antes de entrar. Verifique sua caixa de entrada.';
            } elseif ($loginResult === true) {
                clear_rate_limit_ip($pdo, 'login_attempt');
                redirect('index.php?page=dashboard');
            } else {
                $error = "Login invalido.";
            }
        }
    }
    require __DIR__ . '/views/login.php';
    exit;
}

if ($page === 'register') {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $name = trim($_POST['name'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $password = $_POST['password'] ?? '';

        if (!$name || !$email || !$password) {
            $error = "Preencha todos os campos.";
        } else {
            $pdo = db();
            $stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
            $stmt->execute([$email]);
            if ($stmt->fetchColumn() > 0) {
                $error = "E-mail ja cadastrado.";
            } else {
                $hash = password_hash($password, PASSWORD_DEFAULT);
                // #46 Verificação de e-mail
                $verifyToken = bin2hex(random_bytes(20));
                $needsVerify = db_column_exists($pdo, 'users', 'email_verified');
                if ($needsVerify) {
                    $stmt = $pdo->prepare("INSERT INTO users (name, email, password_hash, role, email_verified, email_verify_token) VALUES (?, ?, ?, 'user', FALSE, ?)");
                    $stmt->execute([$name, $email, $hash, $verifyToken]);
                } else {
                    $stmt = $pdo->prepare("INSERT INTO users (name, email, password_hash, role) VALUES (?, ?, ?, 'user')");
                    $stmt->execute([$name, $email, $hash]);
                }
                $user_id = (int)$pdo->lastInsertId();

                $stmt = $pdo->prepare("SELECT id FROM plans WHERE name = 'Free' LIMIT 1");
                $stmt->execute();
                $plan = $stmt->fetch();
                if ($plan) {
                    $stmt2 = $pdo->prepare("INSERT INTO subscriptions (user_id, plan_id) VALUES (?, ?)");
                    $stmt2->execute([$user_id, $plan['id']]);
                }

                if ($needsVerify) {
                    $verifyLink = app_base_url()
                        . 'index.php?page=verify_email&token=' . urlencode($verifyToken);
                    $html = '<p>Olá, ' . htmlspecialchars($name) . '!</p>'
                        . '<p>Clique no link para confirmar seu e-mail:</p>'
                        . '<p><a href="' . htmlspecialchars($verifyLink) . '">' . htmlspecialchars($verifyLink) . '</a></p>';
                    $mailErr = null;
                    send_email_message($email, '[MonitorPing] Confirme seu e-mail', strip_tags($html), $mailErr, $html);
                    $success = 'Cadastro realizado! Verifique seu e-mail para ativar a conta.';
                } else {
                    login($email, $password);
                    redirect('index.php?page=dashboard');
                }
            }
        }
    }
    require __DIR__ . '/views/register.php';
    exit;
}

if ($page === 'logout') {
    logout();
    redirect('index.php?page=login');
}

if ($page === 'forgot_password') {
    $pdo = db();
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!csrf_check($_POST['csrf_token'] ?? null)) {
            $error = 'Token inválido. Tente novamente.';
        } else {
            $email = trim($_POST['email'] ?? '');
            // Cria tabela de tokens se não existir
            $pdo->exec("CREATE TABLE IF NOT EXISTS password_resets (
                id         SERIAL PRIMARY KEY,
                email      VARCHAR(150) NOT NULL,
                token      VARCHAR(64) NOT NULL UNIQUE,
                expires_at TIMESTAMPTZ NOT NULL,
                used       BOOLEAN NOT NULL DEFAULT FALSE
            )");
            // Mensagem genérica para evitar enumeração de e-mails
            $success = 'Se o e-mail estiver cadastrado, você receberá um link de recuperação em instantes.';
            $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ? AND active = TRUE LIMIT 1");
            $stmt->execute([$email]);
            $usr = $stmt->fetch();
            if ($usr) {
                // Remove tokens antigos do e-mail
                $pdo->prepare("DELETE FROM password_resets WHERE email = ?")->execute([$email]);
                $token = bin2hex(random_bytes(32));
                $pdo->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, NOW() + INTERVAL '1 hour')")
                    ->execute([$email, $token]);
                $resetLink = app_base_url()
                    . 'index.php?page=reset_password&token=' . urlencode($token);
                $html = '<p>Olá,</p><p>Clique no link abaixo para redefinir sua senha (válido por 1 hora):</p>'
                    . '<p><a href="' . htmlspecialchars($resetLink) . '">' . htmlspecialchars($resetLink) . '</a></p>'
                    . '<p>Se você não solicitou isso, ignore este e-mail.</p>';
                send_email_message($email, '[MonitorPing] Recuperação de senha', strip_tags($html), $mailError, $html);
            }
        }
    }
    require __DIR__ . '/views/forgot_password.php';
    exit;
}

if ($page === 'reset_password') {
    $pdo = db();
    $pdo->exec("CREATE TABLE IF NOT EXISTS password_resets (
        id         SERIAL PRIMARY KEY,
        email      VARCHAR(150) NOT NULL,
        token      VARCHAR(64) NOT NULL UNIQUE,
        expires_at TIMESTAMPTZ NOT NULL,
        used       BOOLEAN NOT NULL DEFAULT FALSE
    )");
    $rawToken = $_GET['token'] ?? ($_POST['token'] ?? '');
    if (!$rawToken) {
        redirect('index.php?page=forgot_password');
    }
    $stmt = $pdo->prepare("SELECT * FROM password_resets WHERE token = ? AND used = FALSE AND expires_at > NOW() LIMIT 1");
    $stmt->execute([$rawToken]);
    $resetRow = $stmt->fetch();
    if (!$resetRow) {
        $error = 'Link inválido ou expirado. Solicite um novo link de recuperação.';
    } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!csrf_check($_POST['csrf_token'] ?? null)) {
            $error = 'Token inválido. Tente novamente.';
        } else {
            $pw = $_POST['password'] ?? '';
            $pwc = $_POST['password_confirm'] ?? '';
            if (strlen($pw) < 8) {
                $error = 'A senha deve ter no mínimo 8 caracteres.';
            } elseif ($pw !== $pwc) {
                $error = 'As senhas não coincidem.';
            } else {
                $hash = password_hash($pw, PASSWORD_DEFAULT);
                $pdo->prepare("UPDATE users SET password_hash = ? WHERE email = ?")->execute([$hash, $resetRow['email']]);
                $pdo->prepare("UPDATE password_resets SET used = TRUE WHERE id = ?")->execute([$resetRow['id']]);
                $success = 'Senha redefinida com sucesso!';
                $resetRow = null;
            }
        }
    }
    require __DIR__ . '/views/reset_password.php';
    exit;
}

if ($page === 'verify_email') {
    $token = $_GET['token'] ?? '';
    if ($token) {
        $pdo = db();
        $stmt = $pdo->prepare("SELECT id FROM users WHERE email_verify_token = ? AND email_verified = FALSE LIMIT 1");
        $stmt->execute([$token]);
        $uid = $stmt->fetchColumn();
        if ($uid) {
            $pdo->prepare("UPDATE users SET email_verified = TRUE, email_verify_token = NULL WHERE id = ?")->execute([$uid]);
            $success = 'E-mail confirmado com sucesso! Agora você pode entrar.';
        } else {
            $error = 'Token inválido ou já utilizado.';
        }
    } else {
        $error = 'Token não informado.';
    }
    require __DIR__ . '/views/login.php';
    exit;
}

if ($page === 'verify_2fa') {
    $pending = $_SESSION['pending_2fa_user_id'] ?? null;
    if (!$pending) {
        redirect('index.php?page=login');
    }
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!csrf_check($_POST['csrf_token'] ?? null)) {
            $error = 'Token inválido. Tente novamente.';
        } else {
            $pdo = db();
            $stmt = $pdo->prepare("SELECT totp_secret FROM users WHERE id = ? AND active = TRUE AND totp_enabled = TRUE");
            $stmt->execute([$pending]);
            $row = $stmt->fetch();
            $code = preg_replace('/\D/', '', $_POST['code'] ?? '');
            if ($row && strlen($code) === 6 && totp_verify($row['totp_secret'], $code)) {
                session_regenerate_id(true);
                unset($_SESSION['pending_2fa_user_id']);
                $_SESSION['user_id'] = $pending;
                redirect('index.php?page=dashboard');
            } else {
                $error = 'Código inválido ou expirado. Tente novamente.';
            }
        }
    }
    require __DIR__ . '/views/verify_2fa.php';
    exit;
}

require_login();
$user = current_user();

switch ($page) {
    case 'home':
    case 'dashboard':
        require __DIR__ . '/views/user_dashboard.php';
        break;

    case 'user_ips':
        $pdo = db();
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!csrf_check($_POST['csrf_token'] ?? null)) {
                http_response_code(403);
                exit('CSRF invalido.');
            }
            $action = $_POST['action'] ?? '';
            if ($action === 'delete_ip') {
                $id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
                if ($id) {
                    $stmt = $pdo->prepare("DELETE FROM monitored_ips WHERE id = ? AND user_id = ?");
                    $stmt->execute([$id, $user['id']]);
                }
            } elseif (in_array($action, ['bulk_pause', 'bulk_resume', 'bulk_delete'], true)) {
                $ids = array_map('intval', $_POST['ids'] ?? []);
                if (!empty($ids)) {
                    $ph = implode(',', array_fill(0, count($ids), '?'));
                    if ($action === 'bulk_pause') {
                        $pdo->prepare("UPDATE monitored_ips SET active = FALSE WHERE id IN ($ph) AND user_id = ?")
                            ->execute([...$ids, $user['id']]);
                    } elseif ($action === 'bulk_resume') {
                        $pdo->prepare("UPDATE monitored_ips SET active = TRUE WHERE id IN ($ph) AND user_id = ?")
                            ->execute([...$ids, $user['id']]);
                    } elseif ($action === 'bulk_delete') {
                        $pdo->prepare("DELETE FROM monitored_ips WHERE id IN ($ph) AND user_id = ?")
                            ->execute([...$ids, $user['id']]);
                    }
                }
            }
            redirect('index.php?page=user_ips');
        }
        require __DIR__ . '/views/user_ips.php';
        break;

    case 'api_dashboard':
        require __DIR__ . '/views/api_dashboard.php';
        break;

    case 'api_toggle_ip':
        require __DIR__ . '/views/api_toggle_ip.php';
        break;

    case 'api_check_now':
        require __DIR__ . '/views/api_check_now.php';
        break;

    case 'user_ip_form':
        $pdo = db();
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $label = trim($_POST['label'] ?? '');
            $hostInput = trim($_POST['host'] ?? '');
            $interval_seconds = (int)($_POST['interval_seconds'] ?? 60);
            $timeout_ms = (int)($_POST['timeout_ms'] ?? 1000);
            $alert_email = trim($_POST['alert_email'] ?? '');
            $latency_alert_raw = trim($_POST['latency_alert_ms'] ?? '');
            $latency_alert_ms = $latency_alert_raw !== '' ? max(50, min(60000, (int)$latency_alert_raw)) : null;
            $channelsInput = $_POST['channels'] ?? [];
            $check_method = strtolower(trim($_POST['check_method'] ?? 'auto'));
            $check_port_raw = trim($_POST['check_port'] ?? '');

            if (!csrf_check($_POST['csrf_token'] ?? null)) {
                $error = "CSRF invalido.";
            }

            if (!in_array($check_method, ['auto', 'icmp', 'tcp', 'http', 'https'], true)) {
                $check_method = 'auto';
            }

            // Para HTTP/HTTPS, o host pode ser uma URL completa
            if (in_array($check_method, ['http', 'https'], true)) {
                $host = $hostInput;
                $hostPort = null;
            } else {
                $hostParts = split_host_and_port($hostInput);
                $host = $hostParts['host'];
                $hostPort = $hostParts['port'];
            }

            $check_port = null;
            if ($check_port_raw !== '') {
                if (!ctype_digit($check_port_raw)) {
                    if (empty($error)) {
                        $error = "Porta invalida.";
                    }
                } else {
                    $check_port = (int)$check_port_raw;
                }
            }
            if (empty($error) && $check_port !== null && ($check_port < 1 || $check_port > 65535)) {
                $error = "Porta invalida.";
            }
            if (empty($error) && $check_port !== null && $hostPort !== null && $check_port !== $hostPort) {
                $error = "Porta em conflito com host:porta.";
            }
            if ($check_port === null && $hostPort !== null) {
                $check_port = $hostPort;
            }
            if (empty($error) && $check_method === 'tcp' && $check_port === null) {
                $error = "Informe a porta TCP.";
            }
            if (in_array($check_method, ['icmp', 'http', 'https'], true)) {
                $check_port = null;
            }

            $hostToSave = $host;
            if ($check_port !== null && !in_array($check_method, ['icmp', 'http', 'https'], true)) {
                $hostToSave = $host . ':' . $check_port;
            }

            $hasCheckMethod = ensure_monitored_ips_check_method($pdo);

            $plan = get_user_plan($user['id']);
            $min_interval = (int)$plan['min_interval_seconds'];
            $max_ips = (int)$plan['max_ips'];

            if (empty($error)) {
                if ($interval_seconds < $min_interval) {
                    $error = "Intervalo minimo de {$min_interval} segundos.";
                } elseif (!validate_monitor_host($host, $hostError, $check_method)) {
                    $error = $hostError;
                } else {
                    $current = count_user_ips($user['id']);
                    $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

                    if (!$id && $current >= $max_ips) {
                        $error = "Voce atingiu o limite de IPs do seu plano ({$max_ips}).";
                    } elseif (!$label || !$host) {
                        $error = "Preencha todos os campos obrigatorios.";
                    } else {
                    $hasLatencyAlert = db_column_exists($pdo, 'monitored_ips', 'latency_alert_ms');
                    if ($id) {
                        if ($hasCheckMethod && $hasLatencyAlert) {
                            $stmt = $pdo->prepare("UPDATE monitored_ips SET label=?, host=?, interval_seconds=?, timeout_ms=?, alert_email=?, check_method=?, latency_alert_ms=? WHERE id=? AND user_id=?");
                            $stmt->execute([$label, $hostToSave, $interval_seconds, $timeout_ms, $alert_email ?: null, $check_method, $latency_alert_ms, $id, $user['id']]);
                        } elseif ($hasCheckMethod) {
                            $stmt = $pdo->prepare("UPDATE monitored_ips SET label=?, host=?, interval_seconds=?, timeout_ms=?, alert_email=?, check_method=? WHERE id=? AND user_id=?");
                            $stmt->execute([$label, $hostToSave, $interval_seconds, $timeout_ms, $alert_email ?: null, $check_method, $id, $user['id']]);
                        } else {
                            $stmt = $pdo->prepare("UPDATE monitored_ips SET label=?, host=?, interval_seconds=?, timeout_ms=?, alert_email=? WHERE id=? AND user_id=?");
                            $stmt->execute([$label, $hostToSave, $interval_seconds, $timeout_ms, $alert_email ?: null, $id, $user['id']]);
                        }
                        $ipId = $id;
                    } else {
                        if ($hasCheckMethod && $hasLatencyAlert) {
                            $stmt = $pdo->prepare("INSERT INTO monitored_ips (user_id, label, host, interval_seconds, timeout_ms, alert_email, check_method, latency_alert_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
                            $stmt->execute([$user['id'], $label, $hostToSave, $interval_seconds, $timeout_ms, $alert_email ?: null, $check_method, $latency_alert_ms]);
                        } elseif ($hasCheckMethod) {
                            $stmt = $pdo->prepare("INSERT INTO monitored_ips (user_id, label, host, interval_seconds, timeout_ms, alert_email, check_method) VALUES (?, ?, ?, ?, ?, ?, ?)");
                            $stmt->execute([$user['id'], $label, $hostToSave, $interval_seconds, $timeout_ms, $alert_email ?: null, $check_method]);
                        } else {
                            $stmt = $pdo->prepare("INSERT INTO monitored_ips (user_id, label, host, interval_seconds, timeout_ms, alert_email) VALUES (?, ?, ?, ?, ?, ?)");
                            $stmt->execute([$user['id'], $label, $hostToSave, $interval_seconds, $timeout_ms, $alert_email ?: null]);
                        }
                        $ipId = (int)$pdo->lastInsertId();
                    }
                        sync_alert_channels($ipId, is_array($channelsInput) ? $channelsInput : [], $alert_email ?: null);

                        // Sync tags
                        $tagIds = array_filter(array_map('intval', $_POST['tag_ids'] ?? []));
                        sync_ip_tags($pdo, $ipId, $tagIds);

                        // Salva configuração SSL
                        $sslEnabled = isset($_POST['ssl_check_enabled']) ? 'true' : 'false';
                        $pdo->prepare("UPDATE monitored_ips SET ssl_check_enabled = ? WHERE id = ? AND user_id = ?")
                            ->execute([$sslEnabled, $ipId, $user['id']]);

                        // Realiza um ping imediato ao salvar para ja popular status/latencia
                        $ping = ping_host($hostToSave, $timeout_ms, $check_method);
                        $status = $ping['status'];
                        $latency = $ping['latency_ms'];
                        $pdo->prepare("
                            UPDATE monitored_ips
                            SET last_status = ?, last_latency_ms = ?, last_check_at = NOW()
                            WHERE id = ? AND user_id = ?
                        ")->execute([$status, $latency, $ipId, $user['id']]);
                        $pdo->prepare("
                            INSERT INTO ping_logs (monitored_ip_id, status, latency_ms, checked_at)
                            VALUES (?, ?, ?, NOW())
                        ")->execute([$ipId, $status, $latency]);

                        redirect('index.php?page=user_ips');
                    }
                }
            }
        }
        require __DIR__ . '/views/user_ip_form.php';
        break;

    case 'import_ips':
        require __DIR__ . '/views/import_ips.php';
        break;

    case 'user_logs':
        require __DIR__ . '/views/user_logs.php';
        break;

    case 'user_ip_detail':
        require __DIR__ . '/views/user_ip_detail.php';
        break;

    case 'admin_dashboard':
        require_admin();
        require __DIR__ . '/views/admin_dashboard.php';
        break;

    case 'admin_users':
        require_admin();
        require __DIR__ . '/views/admin_users.php';
        break;

    case 'admin_plans':
        require_admin();
        require __DIR__ . '/views/admin_plans.php';
        break;

    case 'admin_ips':
        require_admin();
        require __DIR__ . '/views/admin_ips.php';
        break;

    case 'admin_logs':
        require_admin();
        require __DIR__ . '/views/admin_logs.php';
        break;

    case 'admin_settings':
        require_admin();
        require __DIR__ . '/views/admin_settings.php';
        break;

    case 'status_page':
        require __DIR__ . '/views/status_page.php';
        break;

    case 'export_logs':
        require __DIR__ . '/views/export_logs.php';
        break;

    case 'export_incidents_pdf':
        require __DIR__ . '/views/export_incidents_pdf.php';
        break;

    case 'user_tags':
        require __DIR__ . '/views/user_tags.php';
        break;

    case 'user_maintenance':
        require __DIR__ . '/views/user_maintenance.php';
        break;

    case 'user_sla':
        require __DIR__ . '/views/user_sla.php';
        break;

    case 'user_api_tokens':
        require __DIR__ . '/views/user_api_tokens.php';
        break;

    case 'admin_saas_metrics':
        require_admin();
        require __DIR__ . '/views/admin_saas_metrics.php';
        break;

    case 'admin_backup':
        require_admin();
        require __DIR__ . '/views/admin_backup.php';
        break;

    case 'admin_backup_download':
        require_admin();
        require __DIR__ . '/views/admin_backup_download.php';
        break;

    case 'admin_license':
        require_admin();
        require __DIR__ . '/views/admin_license.php';
        break;

    case 'admin_whatsapp':
        require_admin();
        require __DIR__ . '/views/admin_whatsapp.php';
        break;

    case 'admin_update':
        require_admin();
        require __DIR__ . '/views/admin_update.php';
        break;

    case 'api_update_trigger':
        require_admin();
        require __DIR__ . '/views/api_update_trigger.php';
        break;

    case 'api_update_log':
        require_admin();
        require __DIR__ . '/views/api_update_log.php';
        break;

    case 'api_whatsapp_proxy':
        require_admin();
        require __DIR__ . '/views/api_whatsapp_proxy.php';
        break;

    case 'setup_2fa':
        $pdo = db();
        // Ensure columns exist
        if (!db_column_exists($pdo, 'users', 'totp_secret')) {
            $pdo->exec("ALTER TABLE users ADD COLUMN IF NOT EXISTS totp_secret VARCHAR(64) NULL");
            $pdo->exec("ALTER TABLE users ADD COLUMN IF NOT EXISTS totp_enabled BOOLEAN NOT NULL DEFAULT FALSE");
        }
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'verify_setup') {
            if (!csrf_check($_POST['csrf_token'] ?? null)) {
                $error = 'Token inválido. Tente novamente.';
            } else {
                $secret = preg_replace('/[^A-Z2-7]/i', '', strtoupper($_POST['secret'] ?? ''));
                $code   = preg_replace('/\D/', '', $_POST['code'] ?? '');
                if (strlen($secret) < 16 || strlen($code) !== 6 || !totp_verify($secret, $code)) {
                    $error = 'Código inválido. Verifique o app e tente novamente.';
                } else {
                    $pdo->prepare("UPDATE users SET totp_secret = ?, totp_enabled = TRUE WHERE id = ?")
                        ->execute([$secret, $user['id']]);
                    unset($_SESSION['totp_setup_secret']);
                    $user['totp_enabled'] = true;
                    redirect('index.php?page=user_profile&2fa=enabled');
                }
            }
        }
        // Generate a temporary secret stored in session (regenerate on each GET)
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($error)) {
            if (empty($_SESSION['totp_setup_secret'])) {
                $_SESSION['totp_setup_secret'] = totp_generate_secret();
            }
        }
        $totp2faSecret = $_SESSION['totp_setup_secret'] ?? totp_generate_secret();
        require __DIR__ . '/views/setup_2fa.php';
        break;

    case 'user_profile':
        $pdo = db();
        if (($_GET['2fa'] ?? '') === 'enabled') {
            $success = '2FA ativado com sucesso!';
        }
        // Garante coluna timezone
        if (!db_column_exists($pdo, 'users', 'timezone')) {
            $pdo->exec("ALTER TABLE users ADD COLUMN timezone VARCHAR(64) NOT NULL DEFAULT 'America/Sao_Paulo'");
        }
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!csrf_check($_POST['csrf_token'] ?? null)) {
                $error = 'Token inválido.';
            } else {
                $action = $_POST['action'] ?? '';
                if ($action === 'update_profile') {
                    $name = trim($_POST['name'] ?? '');
                    $tz = trim($_POST['timezone'] ?? 'America/Sao_Paulo');
                    $validTz = in_array($tz, timezone_identifiers_list(), true) ? $tz : 'America/Sao_Paulo';
                    if (!$name) {
                        $error = 'O nome não pode estar vazio.';
                    } else {
                        $pdo->prepare("UPDATE users SET name = ?, timezone = ? WHERE id = ?")->execute([$name, $validTz, $user['id']]);
                        // Atualiza sessão
                        $_SESSION['user']['name'] = $name;
                        $_SESSION['user']['timezone'] = $validTz;
                        $user['name'] = $name;
                        $user['timezone'] = $validTz;
                        $success = 'Perfil atualizado com sucesso!';
                    }
                } elseif ($action === 'disable_2fa') {
                    $pdo->prepare("UPDATE users SET totp_enabled = FALSE, totp_secret = NULL WHERE id = ?")
                        ->execute([$user['id']]);
                    $user['totp_enabled'] = false;
                    $_SESSION['user']['totp_enabled'] = false;
                    $success = '2FA desativado com sucesso.';
                } elseif ($action === 'change_password') {
                    $current = $_POST['current_password'] ?? '';
                    $new = $_POST['new_password'] ?? '';
                    $confirm = $_POST['new_password_confirm'] ?? '';
                    $stmt2 = $pdo->prepare("SELECT password_hash FROM users WHERE id = ? LIMIT 1");
                    $stmt2->execute([$user['id']]);
                    $hash = $stmt2->fetchColumn();
                    if (!password_verify($current, $hash)) {
                        $error = 'Senha atual incorreta.';
                    } elseif (strlen($new) < 8) {
                        $error = 'A nova senha deve ter no mínimo 8 caracteres.';
                    } elseif ($new !== $confirm) {
                        $error = 'As senhas não coincidem.';
                    } else {
                        $pdo->prepare("UPDATE users SET password_hash = ? WHERE id = ?")->execute([password_hash($new, PASSWORD_DEFAULT), $user['id']]);
                        $success = 'Senha alterada com sucesso!';
                    }
                }
            }
        }
        require __DIR__ . '/views/user_profile.php';
        break;

    default:
        http_response_code(404);
        require __DIR__ . '/includes/header.php';
        echo "<div class='card'><h2>Pagina nao encontrada</h2></div>";
        require __DIR__ . '/includes/footer.php';
        break;
}
