<?php
declare(strict_types=1);

/**
 * EnglishSpeak - Lesson Activities
 * File: teacher/lesson-activities/update.php
 *
 * Word Library -> Flashcard Set -> Lesson Activity -> Student Game
 */

require __DIR__ . '/../partials/auth.php';
require_once __DIR__ . '/../../config/database.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: ../lessons/index.php');
    exit;
}

$pdo = getDbConnection();

$activityId = max(0, (int)($_POST['id'] ?? 0));
$lessonId = max(0, (int)($_POST['lesson_id'] ?? 0));
$title = trim((string)($_POST['title'] ?? ''));
$activityType = trim((string)($_POST['activity_type'] ?? ''));
$instructions = trim((string)($_POST['instructions'] ?? ''));
$flashcardSetId = max(0, (int)($_POST['flashcard_set_id'] ?? 0));
$learningGoal = trim((string)($_POST['learning_goal'] ?? ''));
$difficulty = trim((string)($_POST['difficulty'] ?? 'easy'));
$icon = trim((string)($_POST['icon'] ?? ''));
$requiredXp = max(0, (int)($_POST['required_xp'] ?? 0));
$xpReward = max(0, (int)($_POST['xp_reward'] ?? 10));
$passingScore = max(0, min(100, (int)($_POST['passing_score'] ?? 70)));
$sortOrder = max(0, (int)($_POST['sort_order'] ?? 1));
$status = (string)($_POST['status'] ?? 'active');

$allowedActivityTypes = [
    'flashcards',
    'listen_repeat',
    'speaking',
    'memory',
    'matching',
    'quiz',
    'typing',
    'word_search',
    'sentence_builder',
    'vocabulary',
];

$allowedLearningGoals = [
    'vocabulary',
    'listening',
    'speaking',
    'pronunciation',
    'reading',
    'writing',
    'review',
    'challenge',
];

$allowedDifficulties = ['easy', 'medium', 'hard'];
$allowedStatuses = ['active', 'inactive'];

if (!in_array($activityType, $allowedActivityTypes, true)) {
    $activityType = '';
}

if (!in_array($learningGoal, $allowedLearningGoals, true)) {
    $learningGoal = '';
}

if (!in_array($difficulty, $allowedDifficulties, true)) {
    $difficulty = 'easy';
}

if (!in_array($status, $allowedStatuses, true)) {
    $status = 'active';
}

$old = [
    'lesson_id' => $lessonId,
    'title' => $title,
    'activity_type' => $activityType,
    'instructions' => $instructions,
    'flashcard_set_id' => $flashcardSetId,
    'learning_goal' => $learningGoal,
    'difficulty' => $difficulty,
    'icon' => $icon,
    'required_xp' => $requiredXp,
    'xp_reward' => $xpReward,
    'passing_score' => $passingScore,
    'sort_order' => $sortOrder,
    'status' => $status,
];

$errors = [];

/**
 * @return array<string, array<string, mixed>>
 */
function lauColumns(PDO $pdo, string $table): array
{
    $stmt = $pdo->prepare(
        "SELECT COUNT(*)
         FROM information_schema.TABLES
         WHERE TABLE_SCHEMA = DATABASE()
           AND TABLE_NAME = ?"
    );
    $stmt->execute([$table]);

    if ((int)$stmt->fetchColumn() === 0) {
        return [];
    }

    $rows = $pdo->query("SHOW COLUMNS FROM `{$table}`")->fetchAll(PDO::FETCH_ASSOC);
    return array_column($rows, null, 'Field');
}

$activityColumns = lauColumns($pdo, 'activities');
$setColumns = lauColumns($pdo, 'flashcard_sets');

if ($activityId <= 0) {
    $_SESSION['activities_message'] = 'Invalid Activity ID.';
    $_SESSION['activities_message_type'] = 'error';
    header('Location: ../lessons/index.php');
    exit;
}

$currentStmt = $pdo->prepare(
    "SELECT id, lesson_id
     FROM activities
     WHERE id = ?
     LIMIT 1"
);
$currentStmt->execute([$activityId]);
$currentActivity = $currentStmt->fetch(PDO::FETCH_ASSOC);

if (!$currentActivity) {
    $_SESSION['activities_message'] = 'Activity not found.';
    $_SESSION['activities_message_type'] = 'error';
    header('Location: ../lessons/index.php');
    exit;
}

if ($lessonId <= 0) {
    $lessonId = (int)$currentActivity['lesson_id'];
}

$lessonStmt = $pdo->prepare(
    "SELECT l.id
     FROM lessons l
     INNER JOIN units u ON u.id = l.unit_id
     INNER JOIN books b ON b.id = u.book_id
     WHERE l.id = ?
     LIMIT 1"
);
$lessonStmt->execute([$lessonId]);

if (!$lessonStmt->fetchColumn()) {
    $errors[] = 'The selected Lesson does not exist.';
}

if ($title === '') {
    $errors[] = 'Activity Name is required.';
} elseif (mb_strlen($title) > 150) {
    $errors[] = 'Activity Name must not exceed 150 characters.';
}

if ($activityType === '') {
    $errors[] = 'Please choose a valid Game Template.';
}

if (mb_strlen($instructions) > 5000) {
    $errors[] = 'Instructions are too long.';
}

if (mb_strlen($icon) > 100) {
    $errors[] = 'Icon is too long.';
}

if (isset($activityColumns['flashcard_set_id'])) {
    if ($flashcardSetId > 0) {
        if ($setColumns === []) {
            $errors[] = 'The flashcard_sets table does not exist.';
        } else {
            $setStatusSql = isset($setColumns['status'])
                ? "AND status = 'active'"
                : '';

            $setStmt = $pdo->prepare(
                "SELECT id
                 FROM flashcard_sets
                 WHERE id = ?
                 {$setStatusSql}
                 LIMIT 1"
            );
            $setStmt->execute([$flashcardSetId]);

            if (!$setStmt->fetchColumn()) {
                $errors[] = 'The selected Flashcard Set does not exist or is inactive.';
            }
        }
    }
} elseif ($flashcardSetId > 0) {
    $errors[] = 'The activities table is missing flashcard_set_id.';
}

$titleColumn = isset($activityColumns['title'])
    ? 'title'
    : (isset($activityColumns['name']) ? 'name' : null);

$typeColumn = isset($activityColumns['activity_type'])
    ? 'activity_type'
    : (isset($activityColumns['type']) ? 'type' : null);

if ($titleColumn !== null && $typeColumn !== null && $title !== '' && $activityType !== '') {
    $duplicateStmt = $pdo->prepare(
        "SELECT id
         FROM activities
         WHERE lesson_id = ?
           AND LOWER(TRIM(`{$titleColumn}`)) = LOWER(TRIM(?))
           AND `{$typeColumn}` = ?
           AND id <> ?
         LIMIT 1"
    );
    $duplicateStmt->execute([$lessonId, $title, $activityType, $activityId]);

    if ($duplicateStmt->fetchColumn()) {
        $errors[] = 'An Activity with the same name and Game Template already exists in this Lesson.';
    }
}

if ($errors !== []) {
    $_SESSION['activities_old'] = $old;
    $_SESSION['activities_errors'] = $errors;

    header('Location: edit.php?id=' . $activityId);
    exit;
}

$assignments = [];
$values = [];

$appendValue = static function (
    string $column,
    mixed $value
) use (&$assignments, &$values): void {
    $assignments[] = "`{$column}` = ?";
    $values[] = $value;
};

if (isset($activityColumns['lesson_id'])) {
    $appendValue('lesson_id', $lessonId);
}

if (isset($activityColumns['title'])) {
    $appendValue('title', $title);
} elseif (isset($activityColumns['name'])) {
    $appendValue('name', $title);
}

if (isset($activityColumns['activity_type'])) {
    $appendValue('activity_type', $activityType);
} elseif (isset($activityColumns['type'])) {
    $appendValue('type', $activityType);
}

if (isset($activityColumns['instructions'])) {
    $appendValue('instructions', $instructions !== '' ? $instructions : null);
} elseif (isset($activityColumns['description'])) {
    $appendValue('description', $instructions !== '' ? $instructions : null);
}

if (isset($activityColumns['flashcard_set_id'])) {
    $appendValue('flashcard_set_id', $flashcardSetId > 0 ? $flashcardSetId : null);
}

if (isset($activityColumns['learning_goal'])) {
    $appendValue('learning_goal', $learningGoal !== '' ? $learningGoal : null);
}

if (isset($activityColumns['difficulty'])) {
    $appendValue('difficulty', $difficulty);
}

if (isset($activityColumns['icon'])) {
    $appendValue('icon', $icon !== '' ? $icon : null);
}

if (isset($activityColumns['required_xp'])) {
    $appendValue('required_xp', $requiredXp);
}

if (isset($activityColumns['xp_reward'])) {
    $appendValue('xp_reward', $xpReward);
}

if (isset($activityColumns['passing_score'])) {
    $appendValue('passing_score', $passingScore);
}

if (isset($activityColumns['sort_order'])) {
    $appendValue('sort_order', $sortOrder);
}

if (isset($activityColumns['status'])) {
    $appendValue('status', $status);
}

if (isset($activityColumns['config_json'])) {
    $config = [
        'version' => 1,
        'game_template' => $activityType,
        'shuffle' => true,
    ];

    if ($activityType === 'flashcards') {
        $config['show_image_first'] = true;
        $config['auto_play_audio'] = false;
    }

    $appendValue(
        'config_json',
        json_encode($config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
    );
}

if (isset($activityColumns['updated_at'])) {
    $assignments[] = '`updated_at` = NOW()';
}

try {
    $pdo->beginTransaction();

    $sql = sprintf(
        "UPDATE activities
         SET %s
         WHERE id = ?",
        implode(",\n             ", $assignments)
    );

    $values[] = $activityId;

    $stmt = $pdo->prepare($sql);
    $stmt->execute($values);

    $pdo->commit();

    $_SESSION['activities_message'] = 'Activity updated successfully.';
    $_SESSION['activities_message_type'] = 'success';

    header(
        'Location: ../lessons/activity.php?id='
        . $activityId
        . '&saved=1'
    );
    exit;
} catch (Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }

    error_log('EnglishSpeak lesson-activities/update.php: ' . $e->getMessage());

    $_SESSION['activities_old'] = $old;

    if ($e instanceof PDOException && (string)$e->getCode() === '23000') {
        $_SESSION['activities_errors'] = [
            'This Activity conflicts with existing Lesson or Flashcard Set data.',
        ];
    } else {
        $_SESSION['activities_errors'] = [
            'Could not update the Activity. Please try again.',
        ];
    }

    header('Location: edit.php?id=' . $activityId);
    exit;
}
