<?php
// /elms/admin/courses/game_builder_modal.php
declare(strict_types=1);

if (session_status() === PHP_SESSION_NONE) session_start();

require_once __DIR__ . '/../../includes/db.php';

$mysqli = $mysqli ?? ($conn ?? null);
if (!$mysqli instanceof mysqli) die('Database connection not found.');
$mysqli->set_charset('utf8mb4');

function gbm_esc($s): string {
    return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

$course_id = (int)($_GET['course_id'] ?? 0);
$module_id = (int)($_GET['module_id'] ?? 0);
$load      = (string)($_GET['load'] ?? '');

$loaded = [
    'slug'     => '',
    'title'    => '',
    'type'     => 'mcq',
    'duration' => 60,
    'data'     => [],
];

if ($load !== '') {
    $root = realpath(dirname(__DIR__, 2)); // /elms
    $path = parse_url($load, PHP_URL_PATH) ?: '';
    $file = '';

    if ($root && strpos($path, '/elms/') === 0) {
        $file = $root . substr($path, strlen('/elms'));
    }

    $gamesDir = $root ? ($root . '/uploads/games') : '';

    if (!$file || !is_file($file)) {
        $file = $gamesDir . '/' . basename($path);
    }

    if ($file && is_file($file)) {
        $html = (string)file_get_contents($file);

        if (
            preg_match('~JSON\.parse\(atob\("([^"]+)"\)\)~si', $html, $m) ||
            preg_match('~atob\("([^"]+)"\)~si', $html, $m)
        ) {
            $payload = json_decode(base64_decode($m[1]), true);

            if (is_array($payload)) {
                $loaded['type'] = (string)($payload['type'] ?? 'mcq');
                $loaded['data'] = is_array($payload['data'] ?? null) ? $payload['data'] : [];
                $loaded['duration'] = (int)($loaded['data']['duration'] ?? 60);
            }
        }

        if (preg_match('~<title>(.*?)</title>~si', $html, $tm)) {
            $loaded['title'] = trim(strip_tags($tm[1]));
            $loaded['title'] = preg_replace('~\s*·\s*EDEN CAMPUS\s*$~i', '', $loaded['title']);
        }

        $loaded['slug'] = pathinfo($file, PATHINFO_FILENAME);
    }
}

$validTypes = [
    'mcq',
    'truefalse',
    'match',
    'fill',
    'word',
    'order',
    'wordsearch',
    'memory',
    'crossword',
];

if (!in_array($loaded['type'], $validTypes, true)) {
    $loaded['type'] = 'mcq';
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Game Builder</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body{background:#f8fafc;color:#0f172a}
.type-card{
    border:1px solid #dbe3ef;
    border-radius:16px;
    background:#fff;
    padding:14px;
    cursor:pointer;
    text-align:center;
    height:96px;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    transition:.15s;
}
.type-card:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(15,23,42,.08)}
.type-card.active{border:2px solid #2563eb;background:#eff6ff}
.builder-section{
    background:#fff;
    border:1px solid #e5e7eb;
    border-radius:18px;
    padding:16px;
}
.row-card{
    background:#f8fafc;
    border:1px solid #e2e8f0;
    border-radius:14px;
    padding:14px;
    margin-bottom:12px;
}
.small-help{font-size:.82rem;color:#64748b}
.sticky-actions{
    position:sticky;
    bottom:0;
    z-index:20;
    background:#f8fafc;
    border-top:1px solid #e5e7eb;
}
.answer-note{
    background:#ecfdf5;
    border:1px solid #bbf7d0;
    color:#166534;
    border-radius:14px;
    padding:10px 12px;
    font-size:.85rem;
    font-weight:700;
}
</style>
</head>
<body>

<div class="container-fluid p-3">
<form id="gameForm">
    <input type="hidden" name="course_id" value="<?= (int)$course_id ?>">
    <input type="hidden" name="module_id" value="<?= (int)$module_id ?>">
    <input type="hidden" name="loaded_slug" value="<?= gbm_esc($loaded['slug']) ?>">
    <input type="hidden" name="overwrite" value="<?= $loaded['slug'] !== '' ? '1' : '0' ?>">
    <input type="hidden" name="game_type" id="game_type" value="<?= gbm_esc($loaded['type']) ?>">
    <input type="hidden" name="payload" id="payload_post">

    <div class="row g-3 mb-3">
        <div class="col-md-7">
            <label class="form-label fw-bold">Game Title</label>
            <input class="form-control" name="title" id="title" required value="<?= gbm_esc($loaded['title']) ?>" placeholder="Example: Networking Activity">
        </div>

        <div class="col-md-2">
            <label class="form-label fw-bold">Timer Seconds</label>
            <input type="number" class="form-control" name="duration" id="duration" min="0" value="<?= (int)$loaded['duration'] ?>">
        </div>

        <div class="col-md-3">
            <label class="form-label fw-bold">Background URL</label>
            <input class="form-control" id="bg" placeholder="/elms/uploads/bg.jpg">
        </div>
    </div>

    <div class="row g-3 mb-3" id="typeGrid"></div>

    <div class="builder-section mb-3">
        <div class="d-flex justify-content-between align-items-center gap-2 mb-3">
            <div class="fw-bold">
                Builder: <span class="badge bg-primary" id="typeBadge"></span>
            </div>

            <button type="button" class="btn btn-sm btn-outline-secondary" id="loadSample">
                Load Sample
            </button>
        </div>

        <div class="answer-note mb-3">
            Admin answers මෙතන set කරනවා. Student side එකේ Check කරනකල් answer reveal වෙන්නේ නැහැ.
        </div>

        <div id="builder"></div>
    </div>

    <details class="mb-3">
        <summary class="fw-bold">Advanced JSON</summary>
        <textarea id="payload_raw" class="form-control mt-2" rows="7"></textarea>
        <div class="small-help mt-1">Only for debugging. Normal game build කරන්න මේක edit කරන්න ඕන නැහැ.</div>
    </details>

    <div class="d-flex justify-content-end gap-2 py-2 sticky-actions">
        <button type="button" class="btn btn-outline-secondary" id="previewBtn">Preview</button>
        <button type="submit" class="btn btn-primary px-4 fw-bold">Save Game</button>
    </div>
</form>
</div>

<script>
const loadedData = <?= json_encode($loaded['data'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
const loadedType = <?= json_encode($loaded['type']) ?>;

const types = {
    mcq:['📝','Quiz'],
    truefalse:['✅','Yes / No'],
    match:['🔗','Matching'],
    fill:['✏️','Fill Blanks'],
    word:['🧩','Word Bank'],
    order:['↕️','Line Up'],
    wordsearch:['🔎','Word Search'],
    memory:['🧠','Memory'],
    crossword:['🔳','Crossword']
};

const samples = {
    mcq:{
        questions:[
            {
                q:'What is RAM?',
                options:['Storage','Memory','CPU','Monitor'],
                answer:1,
                img:''
            }
        ]
    },
    truefalse:{
        questions:[
            {q:'RAM is volatile.', answer:true},
            {q:'HTTP uses port 80.', answer:true}
        ]
    },
    match:{
        pairs:[
            {left:'Router', right:'Forwards packets'},
            {left:'Switch', right:'Connects devices'}
        ]
    },
    fill:{
        text:'Photoshop non-destructive editing uses [[layers]] and [[masks]].'
    },
    word:{
        text:'A [[router]] forwards packets between networks.',
        bank:['router','switch','firewall']
    },
    order:{
        items:['Physical','Data Link','Network','Transport']
    },
    wordsearch:{
        words:['NETWORK','SECURITY','FIREWALL']
    },
    memory:{
        pairs:['HTTP','HTTPS','TCP','UDP']
    },
    crossword:{
        entries:[
            {word:'EDEN', clue:'Campus name'},
            {word:'LMS', clue:'Learning Management System'},
            {word:'IT', clue:'Technology course'}
        ]
    }
};

const form = document.getElementById('gameForm');
const typeInput = document.getElementById('game_type');
const typeGrid = document.getElementById('typeGrid');
const badge = document.getElementById('typeBadge');
const builder = document.getElementById('builder');
const payloadPost = document.getElementById('payload_post');
const payloadRaw = document.getElementById('payload_raw');
const durationInput = document.getElementById('duration');
const bgInput = document.getElementById('bg');

let getData = () => ({});

function esc(s){
    return String(s ?? '').replace(/[&<>"']/g, m => ({
        '&':'&amp;',
        '<':'&lt;',
        '>':'&gt;',
        '"':'&quot;',
        "'":'&#39;'
    }[m]));
}

function splitLines(v){
    return String(v || '')
        .split(/\r?\n/)
        .map(x => x.trim())
        .filter(Boolean);
}

function splitComma(v){
    return String(v || '')
        .split(',')
        .map(x => x.trim())
        .filter(Boolean);
}

function lines(v){
    return Array.isArray(v) ? v.join('\n') : '';
}

function field(label, html, help=''){
    return `
        <div class="mb-3">
            <label class="form-label fw-bold">${label}</label>
            ${html}
            ${help ? `<div class="small-help">${help}</div>` : ''}
        </div>
    `;
}

function rowRemoveButton(){
    return `<button type="button" class="btn btn-sm btn-outline-danger remove-row">Remove</button>`;
}

function bindRemove(){
    builder.querySelectorAll('.remove-row').forEach(btn => {
        btn.onclick = () => {
            btn.closest('.row-card')?.remove();
            sync();
        };
    });
}

function buildTypeCards(){
    typeGrid.innerHTML = '';

    Object.entries(types).forEach(([key, info]) => {
        const col = document.createElement('div');
        col.className = 'col-6 col-md-3 col-xl-2';
        col.innerHTML = `
            <div class="type-card" data-type="${key}">
                <div style="font-size:26px">${info[0]}</div>
                <div class="fw-bold">${info[1]}</div>
            </div>
        `;
        typeGrid.appendChild(col);
    });

    typeGrid.querySelectorAll('.type-card').forEach(card => {
        card.onclick = () => render(card.dataset.type, samples[card.dataset.type]);
    });
}

function setActive(type){
    document.querySelectorAll('.type-card').forEach(card => {
        card.classList.toggle('active', card.dataset.type === type);
    });

    typeInput.value = type;
    badge.textContent = (types[type]?.[1] || type).toUpperCase();
}

function render(type, data = null){
    data = data && Object.keys(data).length
        ? data
        : JSON.parse(JSON.stringify(samples[type] || samples.mcq));

    setActive(type);

    if (data.bg) bgInput.value = data.bg;

    if (type === 'mcq') {
        builder.innerHTML = `
            <div id="mcqRows"></div>
            <button type="button" class="btn btn-sm btn-outline-primary" id="addMcq">+ Add Question</button>
        `;

        const box = document.getElementById('mcqRows');

        function add(q = {q:'', options:['','','',''], answer:0, img:''}) {
            const options = q.options && q.options.length ? q.options : ['', '', '', ''];

            const div = document.createElement('div');
            div.className = 'row-card';
            div.innerHTML = `
                ${field('Question', `<input class="form-control q" value="${esc(q.q)}" placeholder="Enter question">`)}
                ${field('Image URL optional', `<input class="form-control img" value="${esc(q.img || '')}" placeholder="/elms/uploads/question.jpg">`)}

                <div class="row g-2">
                    ${[0,1,2,3].map(i => `
                        <div class="col-md-6">
                            <label class="form-label small fw-bold">Option ${i+1}</label>
                            <input class="form-control opt" value="${esc(options[i] || '')}" placeholder="Option ${i+1}">
                        </div>
                    `).join('')}
                </div>

                <div class="mt-3">
                    ${field('Correct Answer', `
                        <select class="form-select ans">
                            ${[0,1,2,3].map(i => `
                                <option value="${i}" ${Number(q.answer) === i ? 'selected' : ''}>Option ${i+1}</option>
                            `).join('')}
                        </select>
                    `)}
                </div>

                ${rowRemoveButton()}
            `;

            box.appendChild(div);
            bindRemove();
            sync();
        }

        (data.questions || samples.mcq.questions).forEach(add);
        document.getElementById('addMcq').onclick = () => add();

        getData = () => ({
            questions: [...box.children].map(row => ({
                q: row.querySelector('.q').value.trim(),
                img: row.querySelector('.img').value.trim(),
                options: [...row.querySelectorAll('.opt')].map(i => i.value.trim()).filter(Boolean),
                answer: parseInt(row.querySelector('.ans').value, 10)
            })).filter(x => x.q && x.options.length >= 2)
        });
    }

    else if (type === 'truefalse') {
        builder.innerHTML = `
            <div id="tfRows"></div>
            <button type="button" class="btn btn-sm btn-outline-primary" id="addTf">+ Add Statement</button>
        `;

        const box = document.getElementById('tfRows');

        function add(q = {q:'', answer:true}) {
            const div = document.createElement('div');
            div.className = 'row-card';
            div.innerHTML = `
                ${field('Statement', `<input class="form-control q" value="${esc(q.q)}" placeholder="Enter statement">`)}
                ${field('Correct Answer', `
                    <select class="form-select ans">
                        <option value="true" ${q.answer ? 'selected' : ''}>True</option>
                        <option value="false" ${!q.answer ? 'selected' : ''}>False</option>
                    </select>
                `)}
                ${rowRemoveButton()}
            `;

            box.appendChild(div);
            bindRemove();
            sync();
        }

        (data.questions || samples.truefalse.questions).forEach(add);
        document.getElementById('addTf').onclick = () => add();

        getData = () => ({
            questions: [...box.children].map(row => ({
                q: row.querySelector('.q').value.trim(),
                answer: row.querySelector('.ans').value === 'true'
            })).filter(x => x.q)
        });
    }

    else if (type === 'match') {
        builder.innerHTML = `
            <div id="pairRows"></div>
            <button type="button" class="btn btn-sm btn-outline-primary" id="addPair">+ Add Pair</button>
        `;

        const box = document.getElementById('pairRows');

        function add(p = {left:'', right:''}) {
            const div = document.createElement('div');
            div.className = 'row-card';
            div.innerHTML = `
                <div class="row g-2">
                    <div class="col-md-6">
                        <label class="form-label fw-bold">Left Item</label>
                        <input class="form-control left" value="${esc(p.left)}" placeholder="Example: Router">
                    </div>
                    <div class="col-md-6">
                        <label class="form-label fw-bold">Right Answer</label>
                        <input class="form-control right" value="${esc(p.right)}" placeholder="Example: Forwards packets">
                    </div>
                </div>
                <div class="mt-2">${rowRemoveButton()}</div>
            `;

            box.appendChild(div);
            bindRemove();
            sync();
        }

        (data.pairs || samples.match.pairs).forEach(add);
        document.getElementById('addPair').onclick = () => add();

        getData = () => ({
            pairs: [...box.children].map(row => ({
                left: row.querySelector('.left').value.trim(),
                right: row.querySelector('.right').value.trim()
            })).filter(x => x.left && x.right)
        });
    }

    else if (type === 'fill') {
        builder.innerHTML = `
            ${field(
                'Paragraph',
                `<textarea id="fillText" class="form-control" rows="6">${esc(data.text || samples.fill.text)}</textarea>`,
                'Use [[answer]] for blanks. Example: RAM is [[volatile]].'
            )}
        `;

        getData = () => ({
            text: document.getElementById('fillText').value.trim()
        });
    }

    else if (type === 'word') {
        builder.innerHTML = `
            ${field(
                'Paragraph',
                `<textarea id="wordText" class="form-control" rows="5">${esc(data.text || samples.word.text)}</textarea>`,
                'Use [[answer]] for blanks.'
            )}

            ${field(
                'Word Bank',
                `<input id="wordBank" class="form-control" value="${esc((data.bank || samples.word.bank).join(', '))}">`,
                'Comma separated words. Example: router, switch, firewall'
            )}
        `;

        getData = () => ({
            text: document.getElementById('wordText').value.trim(),
            bank: splitComma(document.getElementById('wordBank').value)
        });
    }

    else if (type === 'order') {
        builder.innerHTML = `
            <div id="orderRows"></div>
            <button type="button" class="btn btn-sm btn-outline-primary" id="addOrder">+ Add Item</button>
            <div class="small-help mt-2">Add items in correct order. Student side will shuffle them.</div>
        `;

        const box = document.getElementById('orderRows');

        function add(v = '') {
            const div = document.createElement('div');
            div.className = 'row-card';
            div.innerHTML = `
                <input class="form-control item" value="${esc(v)}" placeholder="Item in correct order">
                <div class="mt-2">${rowRemoveButton()}</div>
            `;

            box.appendChild(div);
            bindRemove();
            sync();
        }

        (data.items || samples.order.items).forEach(add);
        document.getElementById('addOrder').addEventListener('click', function(e) {
    e.preventDefault();
    add('');
    sync();
});

        getData = () => ({
            items: [...box.querySelectorAll('.item')].map(i => i.value.trim()).filter(Boolean)
        });
    }

    else if (type === 'wordsearch') {
        builder.innerHTML = `
            ${field(
                'Words',
                `<textarea id="wsWords" class="form-control" rows="6">${esc(lines(data.words || samples.wordsearch.words))}</textarea>`,
                'One word per line. Student grid auto-generate වෙනවා.'
            )}
        `;

        getData = () => ({
            words: splitLines(document.getElementById('wsWords').value).map(x => x.toUpperCase())
        });
    }

    else if (type === 'memory') {
        builder.innerHTML = `
            ${field(
                'Memory Card Labels',
                `<textarea id="memPairs" class="form-control" rows="6">${esc(lines(data.pairs || samples.memory.pairs))}</textarea>`,
                'One label per line. Each label creates 2 matching cards.'
            )}
        `;

        getData = () => ({
            pairs: splitLines(document.getElementById('memPairs').value)
        });
    }


    else if (type === 'crossword') {
        builder.innerHTML = `
            <div id="cwRows"></div>
            <button type="button" class="btn btn-sm btn-outline-primary" id="addCw">+ Add Word</button>
            <div class="small-help mt-2">
                Word + Clue add කරන්න. Student side එකේ grid auto-create වෙනවා. # / . type කරන්න ඕන නැහැ.
            </div>
        `;

        const box = document.getElementById('cwRows');

        function add(e = {word:'', clue:''}) {
            const div = document.createElement('div');
            div.className = 'row-card';
            div.innerHTML = `
                <div class="row g-2">
                    <div class="col-md-4">
                        <label class="form-label fw-bold">Word</label>
                        <input class="form-control word" value="${esc(e.word)}" placeholder="Example: EDEN">
                    </div>
                    <div class="col-md-8">
                        <label class="form-label fw-bold">Clue</label>
                        <input class="form-control clue" value="${esc(e.clue)}" placeholder="Example: Campus name">
                    </div>
                </div>
                <div class="mt-2">${rowRemoveButton()}</div>
            `;

            box.appendChild(div);
            bindRemove();
            sync();
        }

        (data.entries || samples.crossword.entries).forEach(add);
        document.getElementById('addCw').onclick = () => add();

        getData = () => ({
            entries: [...box.children].map(row => ({
                word: row.querySelector('.word').value.trim().toUpperCase().replace(/[^A-Z0-9]/g, ''),
                clue: row.querySelector('.clue').value.trim()
            })).filter(x => x.word && x.clue)
        });
    }

    else {
        render('mcq', samples.mcq);
        return;
    }

    sync();
}

function buildPayload(){
    const data = getData() || {};
    data.duration = parseInt(durationInput.value || '0', 10) || 0;

    const bg = bgInput.value.trim();
    if (bg) data.bg = bg;

    return data;
}

function validate(type, data){
    if (!document.getElementById('title').value.trim()) {
        return 'Please enter game title.';
    }

    if (type === 'mcq') {
        if (!data.questions || !data.questions.length) return 'Add at least one question.';
        for (const q of data.questions) {
            if (!q.q) return 'Question text missing.';
            if (!q.options || q.options.length < 2) return 'Each quiz question needs minimum 2 options.';
            if (q.answer < 0 || q.answer >= q.options.length) return 'Correct answer is wrong in one question.';
        }
    }

    if (type === 'truefalse' && (!data.questions || !data.questions.length)) {
        return 'Add at least one Yes / No statement.';
    }

    if (type === 'match' && (!data.pairs || data.pairs.length < 2)) {
        return 'Matching game needs at least 2 pairs.';
    }

    if (type === 'fill' && (!data.text || !data.text.includes('[['))) {
        return 'Fill Blanks needs [[answer]] inside paragraph.';
    }

    if (type === 'word' && (!data.text || !data.text.includes('[['))) {
        return 'Word Bank needs [[answer]] inside paragraph.';
    }

    if (type === 'word' && (!data.bank || data.bank.length < 1)) {
        return 'Word Bank needs at least one word.';
    }

    if (type === 'order' && (!data.items || data.items.length < 2)) {
        return 'Line Up needs at least 2 items.';
    }

    if (type === 'wordsearch' && (!data.words || data.words.length < 1)) {
        return 'Word Search needs at least one word.';
    }

    if (type === 'memory' && (!data.pairs || data.pairs.length < 2)) {
        return 'Memory needs at least 2 labels.';
    }

    if (type === 'crossword' && (!data.entries || data.entries.length < 2)) {
        return 'Crossword needs at least 2 words.';
    }

    return '';
}

function sync(){
    const data = buildPayload();
    payloadPost.value = JSON.stringify(data);
    payloadRaw.value = JSON.stringify(data, null, 2);
}

document.addEventListener('input', e => {
    if (builder.contains(e.target) || e.target === durationInput || e.target === bgInput) {
        sync();
    }
});

payloadRaw.addEventListener('input', () => {
    try {
        payloadPost.value = JSON.stringify(JSON.parse(payloadRaw.value || '{}'));
    } catch (e) {}
});

document.getElementById('loadSample').onclick = () => {
    render(typeInput.value, samples[typeInput.value]);
};

async function submitGame(preview = false){
    sync();

    let data;
    try {
        data = JSON.parse(payloadPost.value || '{}');
    } catch (e) {
        alert('Invalid JSON payload.');
        return;
    }

    const error = validate(typeInput.value, data);
    if (error) {
        alert(error);
        return;
    }

    const fd = new FormData(form);
    if (preview) fd.append('preview_only', '1');

    const btn = form.querySelector('button[type="submit"]');

    if (!preview) {
        btn.disabled = true;
        btn.textContent = 'Saving...';
    }

    try {
        const res = await fetch('game_save.php', {
            method: 'POST',
            body: fd
        });

        if (preview) {
            const html = await res.text();
            const w = window.open('', '_blank');
            if (w) {
                w.document.open();
                w.document.write(html);
                w.document.close();
            }
            return;
        }

        const json = await res.json();

        if (!json.ok) {
            alert(json.message || 'Save failed.');
            btn.disabled = false;
            btn.textContent = 'Save Game';
            return;
        }

        parent.postMessage({type:'eden-game-saved', url:json.url}, '*');

    } catch (e) {
        console.error(e);
        alert('Save failed. Check game_save.php.');
        btn.disabled = false;
        btn.textContent = 'Save Game';
    }
}

document.getElementById('previewBtn').onclick = () => submitGame(true);

form.addEventListener('submit', e => {
    e.preventDefault();
    submitGame(false);
});

buildTypeCards();
render(loadedType, Object.keys(loadedData || {}).length ? loadedData : samples[loadedType]);
</script>
</body>
</html>