<?php
session_start();
require_once 'db_config.php';
require_once 'GoogleAuthenticator.php';

header('Content-Type: application/json');

$pdo = getDatabaseConnection();
$ga = new GoogleAuthenticator();

$action = $_GET['action'] ?? '';
$input = json_decode(file_get_contents('php://input'), true);

// Auth check for protected actions
$protected_actions = ['get_mfa_status', 'reconfigure_totp', 'get_all_steps', 'save_step', 'delete_step'];
if (in_array($action, $protected_actions)) {
    if (!isset($_SESSION['user_email'])) {
        echo json_encode(['success' => false, 'message' => 'Unauthorized']);
        exit;
    }
    $userEmail = $_SESSION['user_email'];

    // Admin check for specific actions
    $admin_actions = ['get_all_steps', 'save_step', 'delete_step'];
    if (in_array($action, $admin_actions) && empty($_SESSION['is_admin'])) {
        echo json_encode(['success' => false, 'message' => 'Admin access required']);
        exit;
    }
}

if ($action === 'get_mfa_status') {
    $stmt = $pdo->prepare("SELECT preferred_method FROM wizard_users WHERE email = ?");
    $stmt->execute([$userEmail]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    echo json_encode(['success' => true, 'method' => $user['preferred_method'] ?? 'email']);
    exit;
}

if ($action === 'reconfigure_totp') {
    $secret = $ga->createSecret();
    $stmt = $pdo->prepare("UPDATE wizard_users SET preferred_method = 'totp', totp_secret = ? WHERE email = ?");
    $stmt->execute([$secret, $userEmail]);

    echo json_encode([
        'success' => true,
        'qr_url' => $ga->getQRCodeGoogleUrl($userEmail, $secret, 'Asystent IT'),
        'secret' => $secret
    ]);
    exit;
}

if ($action === 'get_all_steps') {
    $stmt = $pdo->query("SELECT * FROM wizard_steps ORDER BY parent_id ASC, id ASC");
    $steps = $stmt->fetchAll(PDO::FETCH_ASSOC);
    echo json_encode(['success' => true, 'steps' => $steps]);
    exit;
}

if ($action === 'save_step') {
    $id = $input['id'] ?? null;
    $parentId = $input['parent_id'] !== '' ? $input['parent_id'] : null;
    $labelPl = $input['label_pl'] ?? '';
    $labelEn = $input['label_en'] ?? '';
    $isFinal = (int) ($input['is_final'] ?? 0);
    $ticketType = $input['ticket_type'] ?? null;

    if ($id) {
        $stmt = $pdo->prepare("UPDATE wizard_steps SET parent_id = ?, label_pl = ?, label_en = ?, is_final = ?, ticket_type = ? WHERE id = ?");
        $stmt->execute([$parentId, $labelPl, $labelEn, $isFinal, $ticketType, $id]);
    } else {
        $stmt = $pdo->prepare("INSERT INTO wizard_steps (parent_id, label_pl, label_en, is_final, ticket_type) VALUES (?, ?, ?, ?, ?)");
        $stmt->execute([$parentId, $labelPl, $labelEn, $isFinal, $ticketType]);
    }
    echo json_encode(['success' => true]);
    exit;
}

if ($action === 'delete_step') {
    $id = $input['id'] ?? null;
    if ($id) {
        // Warning: This doesn't recursively delete children, but it's a start.
        $stmt = $pdo->prepare("DELETE FROM wizard_steps WHERE id = ?");
        $stmt->execute([$id]);
        echo json_encode(['success' => true]);
    } else {
        echo json_encode(['success' => false, 'message' => 'Missing ID']);
    }
    exit;
}

if ($action === 'check_email') {
    $email = filter_var($input['email'] ?? '', FILTER_VALIDATE_EMAIL);
    if (!$email) {
        echo json_encode(['success' => false, 'message' => 'Nieprawidłowy adres e-mail.']);
        exit;
    }

    $stmt = $pdo->prepare("SELECT preferred_method, lockout_until FROM wizard_users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($user) {
        if ($user['lockout_until'] && strtotime($user['lockout_until']) > time()) {
            echo json_encode(['success' => false, 'message' => 'Konto zablokowane. Spróbuj za chwilę.']);
            exit;
        }
        echo json_encode(['success' => true, 'exists' => true, 'method' => $user['preferred_method']]);
    } else {
        // New user: Create a record and send OTP immediately
        $stmt = $pdo->prepare("INSERT INTO wizard_users (email, preferred_method) VALUES (?, 'email')");
        $stmt->execute([$email]);

        if (sendEmailOTP($email, $pdo)) {
            echo json_encode(['success' => true, 'exists' => false, 'otp_sent' => true]);
        } else {
            // Rollback if email fails so they aren't stuck halfway
            $pdo->prepare("DELETE FROM wizard_users WHERE email = ?")->execute([$email]);
            echo json_encode(['success' => false, 'message' => 'Serwer pocztowy jest niedostępny. Spróbuj później.']);
        }
    }
    exit;
}

if ($action === 'setup_method') {
    $email = filter_var($input['email'] ?? '', FILTER_VALIDATE_EMAIL);
    $method = $input['method'] ?? '';

    if (!$email || !in_array($method, ['totp', 'email'])) {
        echo json_encode(['success' => false, 'message' => 'Błędne dane.']);
        exit;
    }

    // Security check: Must have verified this email in current session
    if (!isset($_SESSION['verified_email']) || $_SESSION['verified_email'] !== $email) {
        echo json_encode(['success' => false, 'message' => 'Wymagana weryfikacja e-mail przed ustawieniem metody.']);
        exit;
    }

    $secret = ($method === 'totp') ? $ga->createSecret() : null;

    $stmt = $pdo->prepare("INSERT INTO wizard_users (email, preferred_method, totp_secret) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE preferred_method = ?, totp_secret = ?");
    $stmt->execute([$email, $method, $secret, $method, $secret]);

    $response = ['success' => true];
    if ($method === 'totp') {
        $response['qr_url'] = $ga->getQRCodeGoogleUrl($email, $secret, 'Asystent IT');
        $response['secret'] = $secret;
    } else {
        // Send first email OTP
        sendEmailOTP($email, $pdo);
    }
    echo json_encode($response);
    exit;
}

if ($action === 'request_email_otp') {
    $email = filter_var($input['email'] ?? '', FILTER_VALIDATE_EMAIL);
    if (!$email) {
        echo json_encode(['success' => false, 'message' => 'Nieprawidłowy e-mail.']);
        exit;
    }

    // Ensure user exists
    $stmt = $pdo->prepare("SELECT id FROM wizard_users WHERE email = ?");
    $stmt->execute([$email]);
    if (!$stmt->fetch()) {
        echo json_encode(['success' => false, 'message' => 'Użytkownik nie istnieje.']);
        exit;
    }

    if (sendEmailOTP($email, $pdo)) {
        echo json_encode(['success' => true]);
    } else {
        echo json_encode(['success' => false, 'message' => 'Błąd wysyłki maila. Sprawdź konfigurację serwera.']);
    }
    exit;
}

if ($action === 'verify') {
    $email = filter_var($input['email'] ?? '', FILTER_VALIDATE_EMAIL);
    $code = $input['code'] ?? '';

    $stmt = $pdo->prepare("SELECT * FROM wizard_users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$user) {
        echo json_encode(['success' => false, 'message' => 'Użytkownik nie istnieje.']);
        exit;
    }

    if ($user['lockout_until'] && strtotime($user['lockout_until']) > time()) {
        echo json_encode(['success' => false, 'message' => 'Konto nadal zablokowane.']);
        exit;
    }

    $isValid = false;
    $methodUsed = '';

    // Check Email OTP first (backup/reset)
    if ($user['email_code'] && $user['email_code'] === $code && strtotime($user['email_code_expires']) > time()) {
        $isValid = true;
        $methodUsed = 'email';

        // If user was using TOTP but verified via Email, they might have lost their app.
        // We can either switch them to email or just let them in. 
        // Let's switch them to 'email' to be helpful.
        if ($user['preferred_method'] === 'totp') {
            $stmt = $pdo->prepare("UPDATE wizard_users SET preferred_method = 'email' WHERE id = ?");
            $stmt->execute([$user['id']]);
        }
    }
    // Otherwise check preferred method (TOTP)
    else if ($user['preferred_method'] === 'totp') {
        if ($ga->verifyCode($user['totp_secret'], $code, 2)) {
            $isValid = true;
            $methodUsed = 'totp';
        }
    }

    if ($isValid) {
        $stmt = $pdo->prepare("UPDATE wizard_users SET attempts = 0, lockout_until = NULL, email_code = NULL WHERE id = ?");
        $stmt->execute([$user['id']]);

        $_SESSION['user_email'] = $email;
        $_SESSION['is_admin'] = (bool) ($user['is_admin'] ?? false);
        $_SESSION['verified_email'] = $email; // Mark as verified for setup_method

        // Fetch Computer Info from GLPI tables based on user email
        try {
            $compStmt = $pdo->prepare("SELECT name, serial FROM glpi_computers WHERE users_id = (SELECT users_id FROM glpi_useremails WHERE email = ? LIMIT 1)");
            $compStmt->execute([$email]);
            $computers = $compStmt->fetchAll(PDO::FETCH_ASSOC);

            if (count($computers) > 0) {
                $first = $computers[0];
                $_SESSION['computer_name'] = $first['name'] ?? 'Brak nazwy';
                $_SESSION['computer_serial'] = $first['serial'] ?? 'Brak S/N';

                // If there's more than one, we tag it so the UI can show a hint
                if (count($computers) > 1) {
                    $_SESSION['computer_name'] .= ' (+' . (count($computers) - 1) . ')';
                }
            } else {
                $_SESSION['computer_name'] = 'Nie znaleziono';
                $_SESSION['computer_serial'] = 'Nie znaleziono';
            }
        } catch (Exception $e) {
            $_SESSION['computer_name'] = 'Błąd bazy';
            $_SESSION['computer_serial'] = 'Błąd bazy';
        }

        $response = ['success' => true, 'is_admin' => $_SESSION['is_admin']];
        // If it's a new user (no preferred method yet, or it was just set to default 'email' during registration)
        // Actually, we set it to 'email' by default, but let's check if they have a TOTP secret or if they haven't "chosen" yet.
        // We can check if it's the first time they verify.
        if (!$user['preferred_method'] || ($user['preferred_method'] === 'email' && !$user['totp_secret'] && !$user['is_admin'])) {
            // Check if they need to CHOOSE a method. 
            // In setup_method we set it, but for new users we want to force the choice.
            // Let's use a simpler check: if this is a new registration flow.
            // We'll return needs_setup if they logged in via email OTP and haven't set up TOTP yet and are not admin.
            // But wait, existing email users also use email OTP. 
            // Let's check if the user record was just created.
            // A better way: check if preferred_method is NULL or if they haven't finished wizard?
            // For now, let's assume if it's email method and they just verified, they might want to switch to TOTP or just continue.
            // The prompt says: "Po podaniu adresu e-mail system od razu proponuje ustawienie TOTP. To błąd bo mozna sobie taką autoryzację ustawić na dowolny adres e-mail."
            // So after verification, we show the choice.
            if (!$user['preferred_method'] || ($user['email_code'] !== null && empty($user['totp_secret']) && empty($user['is_admin']))) {
                $response['needs_setup'] = true;
            }
        }

        // Refined legacy check: if they have NO preferred method or it's a fresh registration
        // Let's just track if they were already "known" or not.

        echo json_encode($response);
    } else {
        $attempts = $user['attempts'] + 1;
        $lockout = null;
        if ($attempts >= 3) {
            $lockout = date('Y-m-d H:i:s', time() + 300); // 5 mins
            $attempts = 0;
        }
        $stmt = $pdo->prepare("UPDATE wizard_users SET attempts = ?, lockout_until = ? WHERE id = ?");
        $stmt->execute([$attempts, $lockout, $user['id']]);

        $msg = ($lockout) ? 'Zbyt wiele prób. Blokada na 5 minut.' : 'Błędny kod.';
        echo json_encode(['success' => false, 'message' => $msg]);
    }
    exit;
}

function sendEmailOTP($email, $pdo)
{
    global $sender_domain, $company_name, $system_email;
    $code = sprintf("%06d", mt_rand(0, 999999));
    $expires = date('Y-m-d H:i:s', time() + 600); // 10 mins

    $stmt = $pdo->prepare("UPDATE wizard_users SET email_code = ?, email_code_expires = ? WHERE email = ?");
    $stmt->execute([$code, $expires, $email]);

    $subjectText = "Kod weryfikacyjny - $company_name";
    $subjectEncoded = "=?UTF-8?B?" . base64_encode($subjectText) . "?=";

    $message = "Twój kod do logowania to: $code\n\nKod jest ważny przez 10 minut.";

    $headers = "MIME-Version: 1.0" . "\r\n";
    $headers .= "Content-Type: text/plain; charset=UTF-8" . "\r\n";
    $headers .= "From: $company_name <$system_email>" . "\r\n";
    $headers .= "Reply-To: $system_email" . "\r\n";
    $headers .= "X-Mailer: PHP/" . phpversion();

    return sendEmailSMTP($system_email, $email, $subjectText, $message, $headers);
}
?>