<?php
include 'includes/header.php';
require_once 'db/config.php';

// --- Security & Utility Functions ---

/**
 * Executes user-submitted Python code in a sandboxed environment.
 *
 * WARNING: This is a placeholder and is NOT secure for a production environment.
 * It uses shell_exec, which is highly insecure. This MUST be replaced with a
 * proper sandboxed execution engine (e.g., Docker containers, r-jail, etc.).
 *
 * @param string $solution The Python code to execute.
 * @return string The output from the executed code.
 */
function execute_python_safely(string $solution): string
{
    // Create a temporary file to hold the user's code
    $temp_file = tempnam(sys_get_temp_dir(), 'user_solution_') . '.py';
    file_put_contents($temp_file, $solution);

    // Construct the command to execute the Python script.
    // The `2>&1` redirects stderr to stdout to capture any errors.
    $command = 'python3 ' . escapeshellarg($temp_file) . ' 2>&1';

    // Execute the command
    $output = shell_exec($command);

    // Clean up the temporary file
    unlink($temp_file);

    return $output ?? '';
}

/**
 * Compares the actual output with the expected output, ignoring whitespace differences.
 *
 * @param string $actualOutput The output from the user's code.
 * @param string $expectedOutput The correct output from the database.
 * @return bool True if the outputs match, false otherwise.
 */
function compare_outputs(string $actualOutput, string $expectedOutput): bool
{
    return trim($actualOutput) === trim($expectedOutput);
}

/**
 * Awards a specific badge to a user if they don't already have it.
 *
 * @param PDO $pdo The database connection.
 * @param int $user_id The user's ID.
 * @param string $badgeName The name of the badge to award.
 */
function award_badge(PDO $pdo, int $user_id, string $badgeName): void
{
    // Find the badge ID
    $stmt = $pdo->prepare('SELECT id FROM badges WHERE name = ?');
    $stmt->execute([$badgeName]);
    $badge = $stmt->fetch();

    if ($badge) {
        // Insert the badge for the user, ignoring duplicates
        $stmt = $pdo->prepare('INSERT IGNORE INTO user_badges (user_id, badge_id) VALUES (?, ?)');
        $stmt->execute([$user_id, $badge['id']]);
    }
}


// --- Main Logic ---

if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}

$user_id = $_SESSION['user_id'];

if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['challenge_id'], $_POST['solution'])) {
    header('Location: challenges.php');
    exit;
}

$challenge_id = $_POST['challenge_id'];
$solution = $_POST['solution'];
$language = $_POST['language'] ?? 'python'; // Default to python

if (empty($solution)) {
    $_SESSION['error_message'] = 'Please provide a solution.';
    header('Location: challenge.php?id=' . $challenge_id);
    exit;
}

$pdo = db();

// Get challenge details
$stmt = $pdo->prepare('SELECT name, expected_output FROM challenges WHERE id = ?');
$stmt->execute([$challenge_id]);
$challenge = $stmt->fetch();

if (!$challenge) {
    header('Location: challenges.php');
    exit;
}

// --- Grading ---
$status = 'pending';
if ($language === 'python') {
    $actual_output = execute_python_safely($solution);
    if (compare_outputs($actual_output, $challenge['expected_output'])) {
        $status = 'passed';
    } else {
        $status = 'failed';
    }
}

// --- Record Submission ---
$stmt = $pdo->prepare('
    INSERT INTO challenge_submissions (user_id, challenge_id, language, submission_content, status)
    VALUES (?, ?, ?, ?, ?)
');
$stmt->execute([$user_id, $challenge_id, $language, $solution, $status]);

// --- Post-Submission Actions ---
if ($status === 'passed') {
    $_SESSION['success_message'] = "Correct solution for '{$challenge['name']}'! Well done!";

    // Award "First Challenge Completed" badge if it's their first
    $stmt = $pdo->prepare('SELECT COUNT(*) as passed_count FROM challenge_submissions WHERE user_id = ? AND status = 'passed'');
    $stmt->execute([$user_id]);
    $result = $stmt->fetch();

    if ($result && $result['passed_count'] === 1) {
        award_badge($pdo, $user_id, 'First Challenge Completed');
        $_SESSION['success_message'] .= ' You just earned the "First Challenge Completed" badge!';
    }

    // Send congratulatory email
    $stmt = $pdo->prepare('SELECT name, email FROM users WHERE id = ?');
    $stmt->execute([$user_id]);
    $user = $stmt->fetch();

    if ($user) {
        require_once 'mail/MailService.php';
        $subject = 'Congratulations on completing a challenge!';
        $body = "Hello {$user['name']},<br><br>You have successfully completed the '{$challenge['name']}' challenge. Keep up the great work!<br><br>You can view any new badges or certificates in your profile.<br><br>Best regards,<br>The RS Learning Lab Team";
        MailService::sendMail($user['email'], $subject, $body, strip_tags($body));
    }

} elseif ($status === 'failed') {
    $_SESSION['error_message'] = "Your solution for '{$challenge['name']}' is incorrect. Try again!";
} else {
    $_SESSION['info_message'] = 'Your solution has been submitted successfully and is pending review.';
}

header('Location: challenges.php');
exit;
