<?php
declare(strict_types=1);

session_start();

$isPreview = (int)($_GET['preview'] ?? 0) === 1;
$isTeacher = !empty($_SESSION['user_id'])
    && in_array((string)($_SESSION['user_role'] ?? ''), ['teacher', 'admin'], true);
$isStudent = !empty($_SESSION['student_id']);

if ($isPreview) {
    if (!$isTeacher) {
        $_SESSION['teacher_return_url'] = (string)($_SERVER['REQUEST_URI'] ?? '');
        header('Location: ../teacher/login.php');
        exit;
    }
} elseif (!$isStudent) {
    $_SESSION['student_return_url'] = (string)($_SERVER['REQUEST_URI'] ?? '');
    header('Location: student-login.php');
    exit;
}

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/student_activity_navigation.php';
$pdo = getDbConnection();

$bookSlug = trim((string)($_GET['book'] ?? ''));
$levelSlug = trim((string)($_GET['level'] ?? ''));
$levelId = max(0, (int)($_GET['level_id'] ?? 0));
$unitId = max(0, (int)($_GET['unit_id'] ?? ($_GET['id'] ?? 0)));
$lessonId = max(0, (int)($_GET['lesson_id'] ?? 0));
$activityId = max(0, (int)($_GET['activity_id'] ?? ($_GET['activity'] ?? 0)));

if (
    $bookSlug === ''
    || $levelId <= 0
    || $unitId <= 0
    || $lessonId <= 0
    || $activityId <= 0
) {
    header('Location: student-learning.php');
    exit;
}

function smColumns(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');
}

function smAssetUrl(string $path): string
{
    $path = trim($path);

    if ($path === '') {
        return '';
    }

    if (
        str_starts_with($path, 'http://')
        || str_starts_with($path, 'https://')
        || str_starts_with($path, 'data:')
        || str_starts_with($path, '/')
    ) {
        return $path;
    }

    return '/EnglishSpeak/' . ltrim($path, './');
}

$activityColumns = smColumns($pdo, 'activities');
$relationColumns = smColumns($pdo, 'flashcard_set_words');
$wordColumns = smColumns($pdo, 'words');

if (
    $activityColumns === []
    || $relationColumns === []
    || $wordColumns === []
    || !isset($activityColumns['flashcard_set_id'])
) {
    http_response_code(500);
    exit('Thiếu bảng dữ liệu Memory.');
}

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

$setFk = isset($relationColumns['set_id'])
    ? 'set_id'
    : (isset($relationColumns['flashcard_set_id']) ? 'flashcard_set_id' : null);

$wordFk = isset($relationColumns['word_id']) ? 'word_id' : null;

$orderColumn = isset($relationColumns['order_no'])
    ? 'order_no'
    : (isset($relationColumns['sort_order']) ? 'sort_order' : 'id');

$wordTextColumn = isset($wordColumns['word'])
    ? 'word'
    : (isset($wordColumns['term']) ? 'term' : null);

$imageColumn = isset($wordColumns['image_path'])
    ? 'image_path'
    : (isset($wordColumns['image']) ? 'image' : null);

$audioColumn = isset($wordColumns['audio_us_path'])
    ? 'audio_us_path'
    : (isset($wordColumns['audio_path'])
        ? 'audio_path'
        : (isset($wordColumns['audio']) ? 'audio' : null));

if (
    $activityTitleColumn === null
    || $setFk === null
    || $wordFk === null
    || $wordTextColumn === null
) {
    http_response_code(500);
    exit('Cấu trúc dữ liệu Memory chưa đầy đủ.');
}

$activityStatusWhere = isset($activityColumns['status'])
    ? "AND a.status = 'active'"
    : '';


$passingScoreSelect = isset($activityColumns['passing_score'])
    ? 'a.passing_score AS passing_score,'
    : '70 AS passing_score,';

$contextStmt = $pdo->prepare(
    "SELECT
        a.id AS activity_id,
        a.flashcard_set_id,
        a.xp_reward AS xp_reward,
        {$passingScoreSelect}
        a.`{$activityTitleColumn}` AS activity_title,

        le.id AS lesson_id,
        le.lesson_number,
        le.title AS lesson_title,

        u.id AS unit_id,
        u.unit_number,
        u.title AS unit_title,

        l.id AS level_id,
        l.name AS level_name,
        l.slug AS level_slug,

        b.id AS book_id,
        b.name AS book_name,
        b.slug AS book_slug
     FROM activities a
     INNER JOIN lessons le
        ON le.id = a.lesson_id
     INNER JOIN units u
        ON u.id = le.unit_id
     INNER JOIN levels l
        ON l.id = u.level_id
     INNER JOIN books b
        ON b.id = l.book_id
     WHERE a.id = ?
       AND le.id = ?
       AND u.id = ?
       AND l.id = ?
       AND b.slug = ?
       {$activityStatusWhere}
     LIMIT 1"
);
$contextStmt->execute([
    $activityId,
    $lessonId,
    $unitId,
    $levelId,
    $bookSlug,
]);
$activity = $contextStmt->fetch(PDO::FETCH_ASSOC);

if (!$activity) {
    http_response_code(404);
    exit('Không tìm thấy Memory trong cấp độ đã chọn.');
}

$passingScore = max(0, min(100, (int)($activity['passing_score'] ?? 70)));

/*
 * Activity Settings from Student Runtime.
 * Session is the primary source; database fallback keeps direct links working.
 */
$activitySettings = $_SESSION['activity_settings_data'] ?? [];

if ($activitySettings === [] && smColumns($pdo, 'activity_settings') !== []) {
    $settingsStmt = $pdo->prepare(
        'SELECT settings_json FROM activity_settings WHERE activity_id = ? LIMIT 1'
    );
    $settingsStmt->execute([$activityId]);
    $settingsJson = $settingsStmt->fetchColumn();

    if (is_string($settingsJson) && $settingsJson !== '') {
        $decodedSettings = json_decode($settingsJson, true);

        if (is_array($decodedSettings)) {
            $activitySettings = $decodedSettings;
        }
    }
}

$resourceType = strtolower(trim((string)($activitySettings['resource_type'] ?? '')));
$resourceId = max(0, (int)($activitySettings['resource_id'] ?? 0));

$flashcardSetId = (int)$activity['flashcard_set_id'];

if ($resourceType === 'flashcard_set' && $resourceId > 0) {
    $flashcardSetId = $resourceId;
}

$pairsPerSession = max(
    2,
    min(100, (int)($activitySettings['pairs'] ?? 6))
);

$memorySettings = [
    'shuffle' => filter_var(
        $activitySettings['shuffle'] ?? true,
        FILTER_VALIDATE_BOOL
    ),
    'timer_enabled' => filter_var(
        $activitySettings['timer_enabled'] ?? false,
        FILTER_VALIDATE_BOOL
    ),
    'time_limit' => max(
        10,
        min(600, (int)($activitySettings['time_limit'] ?? 60))
    ),
    'layout' => in_array(
        (string)($activitySettings['layout'] ?? 'auto'),
        ['auto', '2-columns', '3-columns'],
        true
    )
        ? (string)($activitySettings['layout'] ?? 'auto')
        : 'auto',
    'allow_retry' => filter_var(
        $activitySettings['allow_retry'] ?? true,
        FILTER_VALIDATE_BOOL
    ),
];

$passingScore = max(
    0,
    min(100, (int)($activitySettings['passing_score'] ?? $passingScore))
);

/* Save shared Student Progress for Memory. */
if (
    ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST'
    && (string)($_POST['action'] ?? '') === 'save_activity_progress'
) {
    header('Content-Type: application/json; charset=utf-8');

    if ($isPreview) {
        echo json_encode(['ok' => true, 'saved' => false, 'reason' => 'preview'], JSON_UNESCAPED_UNICODE);
        exit;
    }

    $studentId = max(0, (int)($_SESSION['student_id'] ?? 0));
    $score = 100;

    if ($studentId <= 0) {
        http_response_code(401);
        echo json_encode(['ok' => false, 'message' => 'Chưa đăng nhập học sinh.'], JSON_UNESCAPED_UNICODE);
        exit;
    }

    $progressColumns = smColumns($pdo, 'student_content_progress');
    foreach ([
        'student_id', 'content_type', 'content_id', 'status', 'best_score',
        'attempt_count', 'xp_earned', 'first_started_at', 'completed_at', 'last_attempt_at'
    ] as $requiredColumn) {
        if (!isset($progressColumns[$requiredColumn])) {
            http_response_code(500);
            echo json_encode([
                'ok' => false,
                'message' => 'Bảng student_content_progress thiếu cột: ' . $requiredColumn,
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }
    }

    $passed = $score >= $passingScore;

    try {
        $pdo->beginTransaction();

        $existingStmt = $pdo->prepare(
            "SELECT id
             FROM student_content_progress
             WHERE student_id = ?
               AND content_type = 'activity'
               AND content_id = ?
             LIMIT 1
             FOR UPDATE"
        );
        $existingStmt->execute([$studentId, $activityId]);
        $existingId = (int)($existingStmt->fetchColumn() ?: 0);

        if ($existingId > 0) {
            $updateStmt = $pdo->prepare(
                "UPDATE student_content_progress
                 SET status = CASE
                        WHEN status = 'completed' OR ? = 1 THEN 'completed'
                        ELSE 'in_progress'
                     END,
                     best_score = GREATEST(COALESCE(best_score, 0), ?),
                     attempt_count = COALESCE(attempt_count, 0) + 1,
                     completed_at = CASE
                        WHEN ? = 1 THEN COALESCE(completed_at, NOW())
                        ELSE completed_at
                     END,
                     last_attempt_at = NOW()
                 WHERE id = ?"
            );
            $updateStmt->execute([$passed ? 1 : 0, $score, $passed ? 1 : 0, $existingId]);
        } else {
            $insertStmt = $pdo->prepare(
                "INSERT INTO student_content_progress (
                    student_id, content_type, content_id, status, best_score,
                    attempt_count, xp_earned, first_started_at, completed_at, last_attempt_at
                 ) VALUES (
                    ?, 'activity', ?, ?, ?, 1, 0, NOW(),
                    CASE WHEN ? = 1 THEN NOW() ELSE NULL END,
                    NOW()
                 )"
            );
            $insertStmt->execute([
                $studentId,
                $activityId,
                $passed ? 'completed' : 'in_progress',
                $score,
                $passed ? 1 : 0,
            ]);
        }

        $pdo->commit();
        echo json_encode([
            'ok' => true,
            'saved' => true,
            'passed' => $passed,
            'score' => $score,
            'passing_score' => $passingScore,
        ], JSON_UNESCAPED_UNICODE);
        exit;
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        http_response_code(500);
        echo json_encode(['ok' => false, 'message' => 'Không thể lưu tiến trình Memory.'], JSON_UNESCAPED_UNICODE);
        exit;
    }
}

$xpReward = max(0, (int)($activity['xp_reward'] ?? 0));
if ($xpReward <= 0) {
    $xpReward = 10;
}

$imageSelect = $imageColumn !== null
    ? "w.`{$imageColumn}` AS image_path"
    : "'' AS image_path";

$audioSelect = $audioColumn !== null
    ? "w.`{$audioColumn}` AS audio_path"
    : "'' AS audio_path";

$wordStatusWhere = isset($wordColumns['status'])
    ? "AND w.status = 'active'"
    : '';

$wordStmt = $pdo->prepare(
    "SELECT
        w.id,
        w.`{$wordTextColumn}` AS word_text,
        {$imageSelect},
        {$audioSelect},
        fsw.`{$orderColumn}` AS display_order
     FROM flashcard_set_words fsw
     INNER JOIN words w
        ON w.id = fsw.`{$wordFk}`
     WHERE fsw.`{$setFk}` = ?
       {$wordStatusWhere}
     ORDER BY fsw.`{$orderColumn}` ASC, fsw.id ASC"
);
$wordStmt->execute([$flashcardSetId]);
$rows = $wordStmt->fetchAll(PDO::FETCH_ASSOC);

$cards = array_map(
    static function (array $row): array {
        return [
            'word' => (string)($row['word_text'] ?? ''),
            'image' => smAssetUrl((string)($row['image_path'] ?? '')),
            'audio' => smAssetUrl((string)($row['audio_path'] ?? '')),
        ];
    },
    $rows
);

if (
    $pairsPerSession < 100
    && count($cards) > $pairsPerSession
) {
    $cards = array_slice($cards, 0, $pairsPerSession);
}

$rawUnitNumber = trim((string)$activity['unit_number']);
$rawLessonNumber = trim((string)$activity['lesson_number']);

$displayUnitNumber = preg_match('/(\d+)/', $rawUnitNumber, $unitMatch)
    ? (int)$unitMatch[1]
    : $rawUnitNumber;

$displayLessonNumber = preg_match('/(\d+)/', $rawLessonNumber, $lessonMatch)
    ? (int)$lessonMatch[1]
    : $rawLessonNumber;

$backUrl = 'student-activities.php?' . http_build_query([
    'book' => (string)$activity['book_slug'],
    'level' => (string)$activity['level_slug'],
    'level_id' => (int)$activity['level_id'],
    'unit_id' => (int)$activity['unit_id'],
    'lesson_id' => (int)$activity['lesson_id'],
    'lesson' => $displayLessonNumber,
]);

/*
 * Điều hướng dùng hàm chung.
 * Nút Tiếp tục chỉ điều hướng; không xử lý XP, score hay progress.
 */
$nextRuntimeUrl = englishSpeakGetNextActivityUrl($pdo, $activityId);

if ($isPreview && str_contains($nextRuntimeUrl, 'student-runtime/index.php')) {
    $nextRuntimeUrl .= (str_contains($nextRuntimeUrl, '?') ? '&' : '?') . 'preview=1';
}

$_SESSION['last_learning_url'] = (string)($_SERVER['REQUEST_URI'] ?? '');
?>
<!doctype html>
<html lang="vi">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>Memory | EnglishSpeak</title>
<style>
:root{
  --blue:#198fe3;--blue-dark:#0868c7;--soft:#eaf5ff;--page:#f4f8fc;
  --text:#15314b;--muted:#718399;--line:#dfe8f0;--green:#26a65b;
  --width:520px;--shadow:0 7px 22px rgba(31,71,108,.10)
}
*{box-sizing:border-box}
html,body{margin:0;min-height:100%;background:var(--page);color:var(--text);font-family:"Segoe UI",Tahoma,Arial,sans-serif}
body{display:flex;justify-content:center}
button,a{font:inherit;-webkit-tap-highlight-color:transparent}
.app{width:min(100%,var(--width));min-height:100dvh;padding:0 12px 24px;background:#fff;box-shadow:0 0 28px rgba(30,79,115,.08)}
.topbar{position:sticky;top:0;z-index:40;display:grid;grid-template-columns:46px minmax(0,1fr) 46px;align-items:center;gap:9px;min-height:76px;margin:0 -12px 14px;padding:12px;background:linear-gradient(135deg,#3488ef,#17b8e4);color:#fff;box-shadow:0 5px 15px rgba(31,135,210,.22)}
.round{display:grid;width:44px;height:44px;place-items:center;border:0;border-radius:50%;background:rgba(255,255,255,.15);color:#fff;text-decoration:none;font-size:24px;font-weight:850;cursor:pointer}
.heading{text-align:center;min-width:0}.heading strong{display:block;font-size:22px;line-height:1.15}.heading small{display:block;margin-top:4px;color:rgba(255,255,255,.92);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lesson{display:grid;grid-template-columns:52px minmax(0,1fr);align-items:center;gap:11px;min-height:72px;margin-bottom:12px;padding:12px 14px;border-radius:20px;background:linear-gradient(135deg,#edf6ff,#e6f1ff)}
.lesson__icon{width:48px;height:48px;display:grid;place-items:center;border-radius:14px;background:#fff;font-size:29px}.lesson strong{font-size:18px}
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:12px}
.stat{padding:10px 8px;border:1px solid var(--line);border-radius:14px;background:#fff;text-align:center}.stat strong{display:block;color:var(--blue-dark);font-size:18px}.stat span{display:block;margin-top:3px;color:var(--muted);font-size:11px}
.memory-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.memory-card{position:relative;min-width:0;aspect-ratio:1/1.16;border:0;background:transparent;perspective:900px;cursor:pointer}
.memory-card__inner{position:absolute;inset:0;transition:transform .25s;transform-style:preserve-3d}
.memory-card.flipped .memory-card__inner,.memory-card.matched .memory-card__inner{transform:rotateY(180deg)}
.memory-face{position:absolute;inset:0;display:grid;place-items:center;overflow:hidden;border:1px solid var(--line);border-radius:16px;backface-visibility:hidden;box-shadow:var(--shadow)}
.memory-front{background:linear-gradient(135deg,#2d88e8,#16a9dc);color:#fff;font-size:28px;font-weight:900}
.memory-front::after{content:"";width:34px;height:5px;border-radius:999px;background:rgba(255,255,255,.34);position:absolute;bottom:12px}
.memory-back{padding:8px;background:#fff;transform:rotateY(180deg)}
.memory-back img{width:100%;height:100%;object-fit:contain}
.memory-word{padding:8px;color:var(--blue-dark);font-size:clamp(16px,4.8vw,22px);font-weight:850;text-align:center;line-height:1.2;overflow-wrap:anywhere}
.memory-card.matched .memory-back{border:2px solid #7dd69c;background:#f1fff5}
.actions{display:grid;gap:10px;margin-top:14px}
.actions--center{grid-template-columns:minmax(170px,230px);justify-content:center}
.action{min-height:50px;border:1px solid #cbddeb;border-radius:15px;background:#fff;color:var(--text);font-weight:850;cursor:pointer}
.action--restart{width:100%}
.action.primary{border-color:var(--blue);background:var(--blue);color:#fff}
.finish{display:none;min-height:calc(100dvh - 110px);padding:38px 18px;align-items:center;justify-content:center;flex-direction:column;text-align:center}
.finish.show{display:flex}.finish__icon{font-size:66px}.finish h2{margin:14px 0 8px;color:#123e62;font-size:35px}.finish p{margin:0;color:var(--muted);font-size:16px}
.summary{width:100%;margin-top:22px;padding:5px 17px;border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow)}
.summary-row{display:flex;justify-content:space-between;align-items:center;min-height:58px;border-bottom:1px solid #e5ecf2}.summary-row:last-child{border:0}.summary-row strong{color:var(--blue-dark);font-size:19px}
.finish-message{width:100%;margin-top:16px;padding:15px;border:1px solid #bde7c8;border-radius:16px;background:#eefbf1;color:#16823b;font-weight:750}
.finish-actions{display:grid;gap:10px;width:100%;margin-top:18px}.finish-actions button,.finish-actions a{min-height:54px;display:grid;place-items:center;border:1px solid var(--blue);border-radius:15px;background:#fff;color:var(--blue-dark);text-decoration:none;font-weight:850}.finish-actions .primary{background:var(--blue);color:#fff}
.empty{padding:50px 20px;text-align:center}
@media(max-width:390px){
  .app{padding-left:10px;padding-right:10px}
  .topbar{margin-left:-10px;margin-right:-10px;padding-left:10px;padding-right:10px}
  .memory-grid{gap:8px}
  .memory-card{aspect-ratio:1/1.18}
  .memory-front{font-size:25px}
  .memory-word{font-size:15px}
  .stats{gap:6px}
  .stat{padding:9px 5px}
}

/* EnglishSpeak XP popup */
.xp-popup {
    position: fixed;
    z-index: 10000;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(18, 49, 74, .38);
    backdrop-filter: blur(5px);
}
.xp-popup.show { display: flex; }
.xp-popup__card {
    width: min(100%, 350px);
    padding: 24px 20px 20px;
    border-radius: 24px;
    background: #fff;
    box-shadow: 0 18px 50px rgba(18, 49, 74, .24);
    text-align: center;
    animation: xpPopupIn .25s ease-out;
}
.xp-popup__icon {
    width: 76px;
    height: 76px;
    display: grid;
    place-items: center;
    margin: 0 auto 10px;
    border-radius: 50%;
    background: linear-gradient(135deg, #fff6bf, #ffe06e);
    font-size: 42px;
}
.xp-popup__title {
    margin: 0;
    color: #15314b;
    font-size: 27px;
    line-height: 1.2;
}
.xp-popup__text {
    margin: 7px 0 0;
    color: #718399;
    font-size: 14px;
}
.xp-popup__score {
    margin: 17px 0;
    color: #f39c12;
    font-size: 36px;
    font-weight: 900;
    line-height: 1;
}
.xp-popup__button {
    width: 100%;
    min-height: 52px;
    border: 0;
    border-radius: 15px;
    background: linear-gradient(135deg, #237fe1, #159ddd);
    color: #fff;
    font-weight: 850;
    cursor: pointer;
}
@keyframes xpPopupIn {
    from { opacity: 0; transform: translateY(14px) scale(.96); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

</style>
</head>
<body>
<main class="app">
<header class="topbar">
  <a class="round" href="<?= htmlspecialchars($backUrl, ENT_QUOTES, 'UTF-8') ?>" aria-label="Quay lại">←</a>
  <div class="heading">
    <strong>Unit <?= $displayUnitNumber ?></strong>
    <small><?= htmlspecialchars((string)($activity['unit_title'] ?? ''), ENT_QUOTES, 'UTF-8') ?></small>
  </div>
  <span class="round" aria-hidden="true" style="visibility:hidden"></span>
</header>

<?php if ($cards === []): ?>
<section class="empty"><h2>Chưa có từ vựng</h2><p>Hoạt động này chưa có dữ liệu.</p></section>
<?php else: ?>
<section id="gameScreen">
  <div class="lesson"><div class="lesson__icon">🧠</div><strong>Memory</strong></div>
  <div class="stats">
    <div class="stat"><strong id="moves">0</strong><span>Lượt</span></div>
    <div class="stat"><strong id="pairs">0 / <?= count($cards) ?></strong><span>Cặp đúng</span></div>
    <div class="stat"><strong id="time">00:00</strong><span>Thời gian</span></div>
  </div>
  <section
    class="memory-grid"
    id="memoryGrid"
    aria-label="Trò chơi ghi nhớ"
    data-layout="<?= htmlspecialchars((string)$memorySettings['layout'], ENT_QUOTES, 'UTF-8') ?>"
></section>
</section>

<section class="finish" id="finishScreen">
  <div class="finish__icon">🎉</div>
  <h2>Hoàn thành!</h2>
  <p>Em đã ghép đúng tất cả các cặp.</p>
  <div class="summary">
    <div class="summary-row"><span>Điểm</span><strong id="finalScore">100/100</strong></div>
    <div class="summary-row"><span>Cặp đúng</span><strong><?= count($cards) ?> / <?= count($cards) ?></strong></div>
    <div class="summary-row"><span>Số lượt</span><strong id="finalMoves">0</strong></div>
    <div class="summary-row"><span>Thời gian</span><strong id="finalTime">00:00</strong></div>
  </div>
  
  <div class="finish-actions">
    <?php if ($nextRuntimeUrl !== ''): ?>
      <a
        class="primary"
        id="continueButton"
        href="<?= htmlspecialchars($nextRuntimeUrl, ENT_QUOTES, 'UTF-8') ?>"
        hidden
        style="display:none"
      >➡ Next</a>
    <?php endif; ?>

    <button id="playAgainButton" type="button">↻ Again</button>

    <a href="<?= htmlspecialchars($backUrl, ENT_QUOTES, 'UTF-8') ?>">← Back</a>
  </div>
</section>
<?php endif; ?>
</main>


<div class="xp-popup" id="xpPopup" role="dialog" aria-modal="true" aria-labelledby="xpPopupTitle">
    <div class="xp-popup__card">
        <div class="xp-popup__icon" aria-hidden="true">⭐</div>
        <h2 class="xp-popup__title" id="xpPopupTitle">Hoàn thành!</h2>
        <p class="xp-popup__text" id="xpPopupText">Em nhận được</p>
        <div class="xp-popup__score" id="xpPopupScore"></div>
        <button class="xp-popup__button" id="xpPopupButton" type="button">Xem kết quả</button>
    </div>
</div>

<?php if ($cards !== []): ?>
<script>

function showXpPopup(result) {
  if (!result || result.preview === true) return;

  const popup = document.getElementById('xpPopup');
  const title = document.getElementById('xpPopupTitle');
  const text = document.getElementById('xpPopupText');
  const score = document.getElementById('xpPopupScore');

  if (!popup || !title || !text || !score) return;

  const xpAdded = Number(result.xp_added || 0);
  const passed = result.passed === true;

  if (xpAdded > 0) {
    title.textContent = result.xp_event_type === 'completion'
      ? 'Hoàn thành!'
      : 'Luyện tập tốt!';
    text.hidden = false;
    text.textContent = 'Em nhận được';
    score.textContent = `+${xpAdded} XP`;
  } else if (passed) {
    /*
     * Đã hết Practice XP:
     * chỉ khen và hiển thị phần trăm, không nhắc việc hết XP.
     */
    title.textContent = 'Great!';
    text.textContent = '';
    text.hidden = true;
    score.textContent = '100%';
  } else {
    title.textContent = 'Cố gắng nhé!';
    text.hidden = false;
    text.textContent = 'Em cần đạt điểm yêu cầu để nhận XP.';
    score.textContent = '';
  }

  popup.classList.add('show');
}
function hideXpPopup(){
  const popup=document.getElementById('xpPopup');
  if(popup) popup.classList.remove('show');
}
document.getElementById('xpPopupButton')?.addEventListener('click',hideXpPopup);


const sourceCards = <?= json_encode($cards, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>;
const memorySettings = <?= json_encode(
    $memorySettings,
    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
) ?>;
const grid=document.getElementById('memoryGrid');
const movesEl=document.getElementById('moves'),pairsEl=document.getElementById('pairs'),timeEl=document.getElementById('time');
const gameScreen=document.getElementById('gameScreen'),finishScreen=document.getElementById('finishScreen');
const passingScore=<?= (int)$passingScore ?>;
let deck=[],first=null,second=null,lock=false,moves=0,matched=0,wrongAttempts=0,startTime=0,timer=null,soundOn=true;

async function saveActivityProgress(score=100,completed=true){
  try{
    const response=await fetch(
      '/EnglishSpeak/api/save-activity-progress.php',
      {
        method:'POST',
        headers:{'Content-Type':'application/json;charset=UTF-8'},
        credentials:'same-origin',
        body:JSON.stringify({
          activity_id:<?= (int)$activityId ?>,
          score:Math.max(0,Math.min(100,Math.round(Number(score)||0))),
          completed:Boolean(completed),
          passing_score:<?= (int)$passingScore ?>,
          preview:<?= $isPreview ? 'true' : 'false' ?>
        })
      }
    );

    const result=await response.json();

    if(!response.ok||!result.ok){
      console.warn('Không thể lưu tiến trình Memory.',result);
    }

    return result;
  }catch(error){
    console.warn('Lỗi mạng khi lưu tiến trình Memory.',error);
    return {ok:false,xp_added:0};
  }
}

function shuffle(arr){for(let i=arr.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[arr[i],arr[j]]=[arr[j],arr[i]]}return arr}
function buildDeck(){
  const pairs=[];
  sourceCards.forEach((c,i)=>{
    pairs.push({id:`${i}-image`,pair:i,type:'image',content:c.image||'',word:c.word,audio:c.audio||''});
    pairs.push({id:`${i}-word`,pair:i,type:'word',content:c.word,word:c.word,audio:c.audio||''});
  });
  return memorySettings.shuffle ? shuffle(pairs) : pairs;
}
function formatTime(sec){const m=Math.floor(sec/60).toString().padStart(2,'0'),s=(sec%60).toString().padStart(2,'0');return `${m}:${s}`}
function startTimer(){
  clearInterval(timer);
  startTime=Date.now();

  if(!memorySettings.timer_enabled){
    timeEl.textContent='--:--';
    return;
  }

  timer=setInterval(()=>{
    const elapsed=Math.floor((Date.now()-startTime)/1000);
    const remaining=Math.max(0,Number(memorySettings.time_limit||60)-elapsed);
    timeEl.textContent=formatTime(remaining);

    if(remaining<=0){
      clearInterval(timer);
      lock=true;
      finish(false);
    }
  },1000);
}
function speak(card){
  if(!soundOn)return;
  if(card.audio){const a=new Audio(card.audio);a.play().catch(()=>tts(card.word))}
  else tts(card.word);
}
function tts(t){if(!('speechSynthesis' in window))return;speechSynthesis.cancel();const u=new SpeechSynthesisUtterance(t);u.lang='en-US';u.rate=.72;speechSynthesis.speak(u)}
function render(){
  grid.innerHTML='';
  deck.forEach(card=>{
    const btn=document.createElement('button');btn.className='memory-card';btn.type='button';btn.dataset.id=card.id;
    const back=card.type==='image'
      ? (card.content?`<img src="${card.content}" alt="${card.word}">`:`<span class="memory-word">${card.word}</span>`)
      : `<span class="memory-word">${card.word}</span>`;
    btn.innerHTML=`<span class="memory-card__inner"><span class="memory-face memory-front">?</span><span class="memory-face memory-back">${back}</span></span>`;
    btn.onclick=()=>flip(btn,card);grid.appendChild(btn);
  })
}
function flip(el,card){
  if(lock||el.classList.contains('flipped')||el.classList.contains('matched'))return;
  if(!startTime)startTimer();
  el.classList.add('flipped');speak(card);
  if(!first){first={el,card};return}
  second={el,card};moves++;movesEl.textContent=moves;
  if(first.card.pair===second.card.pair&&first.card.id!==second.card.id){
    first.el.classList.add('matched');second.el.classList.add('matched');matched++;pairsEl.textContent=`${matched} / ${sourceCards.length}`;
    first=second=null;
    if(matched===sourceCards.length)setTimeout(finish,450)
  }else{
    wrongAttempts++;
    lock=true;setTimeout(()=>{first.el.classList.remove('flipped');second.el.classList.remove('flipped');first=second=null;lock=false},750)
  }
}
function reset(){
  clearInterval(timer);deck=buildDeck();first=second=null;lock=false;moves=0;matched=0;wrongAttempts=0;startTime=0;

  const layout=String(memorySettings.layout||'auto');
  if(layout==='2-columns'){
    grid.style.gridTemplateColumns='repeat(2,minmax(0,1fr))';
  }else{
    // Auto and 3-columns keep the original compact Memory layout.
    grid.style.gridTemplateColumns='repeat(3,minmax(0,1fr))';
  }

  movesEl.textContent='0';
  pairsEl.textContent=`0 / ${sourceCards.length}`;
  timeEl.textContent=memorySettings.timer_enabled
    ? formatTime(Number(memorySettings.time_limit||60))
    : '--:--';
  render()
}
async function finish(completed=true){
  clearInterval(timer);
  document.getElementById('finalMoves').textContent=moves;
  document.getElementById('finalTime').textContent=timeEl.textContent;

  // Memory score: hoàn thành tất cả cặp bắt đầu từ 100 điểm.
  // Mỗi lần ghép sai trừ 5 điểm. Nếu chưa hoàn thành thì điểm = 0.
  const score=completed
    ? Math.max(0,100-(wrongAttempts*5))
    : 0;

  document.getElementById('finalScore').textContent=`${score}/100`;

  const progressResult=await saveActivityProgress(score,score>=passingScore);

  const continueButton=document.getElementById('continueButton');
  const passed=score>=passingScore;

  if(continueButton){
    continueButton.hidden=!passed;
    continueButton.style.display=passed?'grid':'none';
  }

  gameScreen.style.display='none';
  finishScreen.classList.add('show');
  showXpPopup(progressResult);
}
document.getElementById('playAgainButton')?.addEventListener('click',()=>{
  const continueButton=document.getElementById('continueButton');
  if(continueButton){
    continueButton.hidden=true;
    continueButton.style.display='none';
  }

  finishScreen.classList.remove('show');
  hideXpPopup();
  gameScreen.style.display='block';
  reset();
});
reset();
</script>
<?php endif; ?>
</body>
</html>
