<?php
declare(strict_types=1);

/**
 * EnglishSpeak - Sentence Set Builder V2
 * File: teacher/sentence-sets/detail.php
 *
 * Sentence Library → Sentence Set → Activity Settings → Speaking Sentences
 */

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

$pdo = getDbConnection();

$pageTitle = 'Sentence Set Builder';
$pageSubtitle = 'Select and order reusable sentences for Speaking activities';
$activeTeacherNav = 'content';

$currentUserId = (int)($_SESSION['user_id'] ?? 0);
$currentUserRole = strtolower(trim((string)($_SESSION['user_role'] ?? $_SESSION['role'] ?? 'teacher')));
$isAdmin = $currentUserRole === 'admin';

function ssdv2TableExists(PDO $pdo, string $table): bool
{
    $stmt = $pdo->prepare(
        "SELECT COUNT(*)
         FROM information_schema.TABLES
         WHERE TABLE_SCHEMA = DATABASE()
           AND TABLE_NAME = ?"
    );
    $stmt->execute([$table]);

    return (int)$stmt->fetchColumn() > 0;
}

function ssdv2Columns(PDO $pdo, string $table): array
{
    if (!ssdv2TableExists($pdo, $table)) {
        return [];
    }

    $rows = $pdo
        ->query("SHOW COLUMNS FROM `{$table}`")
        ->fetchAll(PDO::FETCH_ASSOC);

    return array_column($rows, null, 'Field');
}

function ssdv2FirstColumn(array $columns, array $candidates): ?string
{
    foreach ($candidates as $candidate) {
        if (isset($columns[$candidate])) {
            return $candidate;
        }
    }

    return null;
}

function ssdv2Redirect(string $message, string $type = 'success'): never
{
    $_SESSION['sentence_sets_message'] = $message;
    $_SESSION['sentence_sets_message_type'] = $type;

    header('Location: index.php');
    exit;
}

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

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

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

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

function ssdv2NormalizeText(string $text): string
{
    $text = mb_strtolower(trim($text));
    $text = preg_replace('/[^\p{L}\p{N}\s\'-]+/u', ' ', $text) ?? $text;
    $text = preg_replace('/\s+/u', ' ', $text) ?? $text;

    return trim($text);
}

function ssdv2ContainsWholeWord(string $sentence, string $word): bool
{
    $sentence = ssdv2NormalizeText($sentence);
    $word = ssdv2NormalizeText($word);

    if ($sentence === '' || $word === '') {
        return false;
    }

    return preg_match(
        '/(?:^|\s)' . preg_quote($word, '/') . '(?:$|\s)/u',
        $sentence
    ) === 1;
}

foreach (['sentence_sets', 'sentences', 'sentence_set_sentences'] as $table) {
    if (!ssdv2TableExists($pdo, $table)) {
        http_response_code(500);
        exit("Missing required table: {$table}");
    }
}

$setColumns = ssdv2Columns($pdo, 'sentence_sets');
if (!isset($setColumns['created_by_teacher_id'])) { http_response_code(500); exit('Run ADD_OWNER_COLUMN.sql first.'); }
$sentenceColumns = ssdv2Columns($pdo, 'sentences');
$relationColumns = ssdv2Columns($pdo, 'sentence_set_sentences');

$titleColumn = ssdv2FirstColumn($setColumns, ['title', 'name']);
$descriptionColumn = ssdv2FirstColumn($setColumns, ['description']);
$statusColumn = isset($setColumns['status']) ? 'status' : null;
$unitIdColumn = isset($setColumns['unit_id']) ? 'unit_id' : null;
$setSortColumn = ssdv2FirstColumn($setColumns, ['sort_order', 'order_no']);

$sentenceTextColumn = ssdv2FirstColumn(
    $sentenceColumns,
    ['sentence_text', 'sentence', 'text', 'content']
);

$meaningColumn = ssdv2FirstColumn(
    $sentenceColumns,
    ['vietnamese_meaning', 'meaning_vi', 'meaning', 'translation']
);

$ipaColumn = ssdv2FirstColumn(
    $sentenceColumns,
    ['ipa', 'phonetic']
);

$imageColumn = ssdv2FirstColumn(
    $sentenceColumns,
    ['image_path', 'image']
);

$audioColumn = ssdv2FirstColumn(
    $sentenceColumns,
    ['audio_us_path', 'audio_path', 'audio']
);

$sentenceStatusColumn = isset($sentenceColumns['status'])
    ? 'status'
    : null;

$relationSetFk = isset($relationColumns['sentence_set_id'])
    ? 'sentence_set_id'
    : (isset($relationColumns['set_id']) ? 'set_id' : null);

$relationSentenceFk = isset($relationColumns['sentence_id'])
    ? 'sentence_id'
    : null;

$relationOrderColumn = isset($relationColumns['sort_order'])
    ? 'sort_order'
    : (isset($relationColumns['order_no']) ? 'order_no' : null);

if (
    $titleColumn === null
    || $sentenceTextColumn === null
    || $relationSetFk === null
    || $relationSentenceFk === null
) {
    http_response_code(500);
    exit('Sentence Set database structure is incomplete.');
}

$id = max(0, (int)($_GET['id'] ?? $_POST['id'] ?? 0));
$isEdit = $id > 0;

$form = [
    'title' => '',
    'description' => '',
    'status' => 'active',
    'unit_id' => 0,
    'sort_order' => 0,
    'sentence_ids' => [],
];

$error = '';

if ($isEdit) {
    $selects = [
        'id',
        'created_by_teacher_id',
        "`{$titleColumn}` AS title",
        $descriptionColumn !== null
            ? "`{$descriptionColumn}` AS description"
            : "'' AS description",
        $statusColumn !== null
            ? "`{$statusColumn}` AS status"
            : "'active' AS status",
        $unitIdColumn !== null
            ? "`{$unitIdColumn}` AS unit_id"
            : '0 AS unit_id',
        $setSortColumn !== null
            ? "`{$setSortColumn}` AS sort_order"
            : '0 AS sort_order',
    ];

    $stmt = $pdo->prepare(
        'SELECT '
        . implode(', ', $selects)
        . ' FROM sentence_sets WHERE id = ? LIMIT 1'
    );
    $stmt->execute([$id]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
        ssdv2Redirect('Sentence Set not found.', 'error');
    }
    if (!$isAdmin && ($row['created_by_teacher_id'] === null || (int)$row['created_by_teacher_id'] !== $currentUserId)) { http_response_code(403); exit('Bạn không có quyền quản lý Set này.'); }

    $orderSql = $relationOrderColumn !== null
        ? "`{$relationOrderColumn}`, id"
        : 'id';

    $selectedStmt = $pdo->prepare(
        "SELECT `{$relationSentenceFk}` AS sentence_id
         FROM sentence_set_sentences
         WHERE `{$relationSetFk}` = ?
         ORDER BY {$orderSql}"
    );
    $selectedStmt->execute([$id]);

    $form = [
        'title' => (string)$row['title'],
        'description' => (string)$row['description'],
        'status' => (string)$row['status'],
        'unit_id' => (int)$row['unit_id'],
        'sort_order' => (int)$row['sort_order'],
        'sentence_ids' => array_map(
            'intval',
            array_column(
                $selectedStmt->fetchAll(PDO::FETCH_ASSOC),
                'sentence_id'
            )
        ),
    ];
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $title = trim((string)($_POST['title'] ?? ''));
    $description = trim((string)($_POST['description'] ?? ''));
    $status = in_array(
        (string)($_POST['status'] ?? 'active'),
        ['active', 'inactive'],
        true
    )
        ? (string)$_POST['status']
        : 'active';
    $unitId = max(0, (int)($_POST['unit_id'] ?? 0));
    $sortOrder = max(0, (int)($_POST['sort_order'] ?? 0));

    $sentenceIds = array_values(
        array_unique(
            array_filter(
                array_map(
                    'intval',
                    is_array($_POST['sentence_ids'] ?? null)
                        ? $_POST['sentence_ids']
                        : []
                ),
                static fn(int $value): bool => $value > 0
            )
        )
    );

    $form = [
        'title' => $title,
        'description' => $description,
        'status' => $status,
        'unit_id' => $unitId,
        'sort_order' => $sortOrder,
        'sentence_ids' => $sentenceIds,
    ];

    if ($title === '') {
        $error = 'Please enter a Sentence Set title.';
    } elseif ($sentenceIds === []) {
        $error = 'Please select at least one sentence.';
    } else {
        $duplicateSql =
            "SELECT id
             FROM sentence_sets
             WHERE LOWER(TRIM(`{$titleColumn}`)) = LOWER(TRIM(?))";

        $duplicateParams = [$title];

        if ($isEdit) {
            $duplicateSql .= ' AND id <> ?';
            $duplicateParams[] = $id;
        }

        $duplicateSql .= ' LIMIT 1';

        $duplicateStmt = $pdo->prepare($duplicateSql);
        $duplicateStmt->execute($duplicateParams);

        if ($duplicateStmt->fetchColumn()) {
            $error = 'A Sentence Set with this title already exists.';
        }
    }

    if ($error === '') {
        try {
            $pdo->beginTransaction();

            if ($isEdit) {
                $updates = ["`{$titleColumn}` = ?"];
                $params = [$title];

                if ($descriptionColumn !== null) {
                    $updates[] = "`{$descriptionColumn}` = ?";
                    $params[] = $description !== '' ? $description : null;
                }

                if ($statusColumn !== null) {
                    $updates[] = "`{$statusColumn}` = ?";
                    $params[] = $status;
                }

                if ($unitIdColumn !== null) {
                    $updates[] = "`{$unitIdColumn}` = ?";
                    $params[] = $unitId > 0 ? $unitId : null;
                }

                if ($setSortColumn !== null) {
                    $updates[] = "`{$setSortColumn}` = ?";
                    $params[] = $sortOrder;
                }

                if (isset($setColumns['updated_at'])) {
                    $updates[] = 'updated_at = NOW()';
                }

                $params[] = $id;

                $updateStmt = $pdo->prepare(
                    'UPDATE sentence_sets SET '
                    . implode(', ', $updates)
                    . ' WHERE id = ?'
                );
                $updateStmt->execute($params);

                $setId = $id;
            } else {
                $fields = ["`{$titleColumn}`", '`created_by_teacher_id`'];
                $placeholders = ['?', '?'];
                $params = [$title, $isAdmin ? null : $currentUserId];

                if ($descriptionColumn !== null) {
                    $fields[] = "`{$descriptionColumn}`";
                    $placeholders[] = '?';
                    $params[] = $description !== '' ? $description : null;
                }

                if ($statusColumn !== null) {
                    $fields[] = "`{$statusColumn}`";
                    $placeholders[] = '?';
                    $params[] = $status;
                }

                if ($unitIdColumn !== null) {
                    $fields[] = "`{$unitIdColumn}`";
                    $placeholders[] = '?';
                    $params[] = $unitId > 0 ? $unitId : null;
                }

                if ($setSortColumn !== null) {
                    $fields[] = "`{$setSortColumn}`";
                    $placeholders[] = '?';
                    $params[] = $sortOrder;
                }

                $insertStmt = $pdo->prepare(
                    'INSERT INTO sentence_sets ('
                    . implode(', ', $fields)
                    . ') VALUES ('
                    . implode(', ', $placeholders)
                    . ')'
                );
                $insertStmt->execute($params);

                $setId = (int)$pdo->lastInsertId();
            }

            $deleteRelations = $pdo->prepare(
                "DELETE FROM sentence_set_sentences
                 WHERE `{$relationSetFk}` = ?"
            );
            $deleteRelations->execute([$setId]);

            $relationFields = [
                "`{$relationSetFk}`",
                "`{$relationSentenceFk}`",
            ];

            if ($relationOrderColumn !== null) {
                $relationFields[] = "`{$relationOrderColumn}`";
            }

            $relationPlaceholders = array_fill(
                0,
                count($relationFields),
                '?'
            );

            $insertRelation = $pdo->prepare(
                'INSERT INTO sentence_set_sentences ('
                . implode(', ', $relationFields)
                . ') VALUES ('
                . implode(', ', $relationPlaceholders)
                . ')'
            );

            foreach ($sentenceIds as $order => $sentenceId) {
                $relationParams = [$setId, $sentenceId];

                if ($relationOrderColumn !== null) {
                    $relationParams[] = $order + 1;
                }

                $insertRelation->execute($relationParams);
            }

            $pdo->commit();

            ssdv2Redirect(
                $isEdit
                    ? 'Sentence Set updated successfully.'
                    : 'Sentence Set created successfully.'
            );
        } catch (Throwable $exception) {
            if ($pdo->inTransaction()) {
                $pdo->rollBack();
            }

            $error = 'Could not save the Sentence Set.';
        }
    }
}

$meaningSelect = $meaningColumn !== null
    ? "`{$meaningColumn}` AS vietnamese_meaning"
    : "'' AS vietnamese_meaning";

$ipaSelect = $ipaColumn !== null
    ? "`{$ipaColumn}` AS ipa"
    : "'' AS ipa";

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

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

$sentenceStatusWhere = $sentenceStatusColumn !== null
    ? " WHERE `{$sentenceStatusColumn}` = 'active'"
    : '';

$sentenceStmt = $pdo->query(
    "SELECT
        id,
        `{$sentenceTextColumn}` AS sentence_text,
        {$meaningSelect},
        {$ipaSelect},
        {$imageSelect},
        {$audioSelect}
     FROM sentences
     {$sentenceStatusWhere}
     ORDER BY `{$sentenceTextColumn}`, id"
);
$sentences = $sentenceStmt->fetchAll(PDO::FETCH_ASSOC);

/*
 * Reuse an image from Word Library when a sentence has no direct image.
 */
$wordImageMap = [];

if (ssdv2TableExists($pdo, 'words')) {
    $wordColumns = ssdv2Columns($pdo, 'words');

    $wordTextColumn = ssdv2FirstColumn(
        $wordColumns,
        ['word', 'english_word', 'term', 'title', 'name']
    );

    $wordImageColumn = ssdv2FirstColumn(
        $wordColumns,
        ['image_path', 'image', 'image_url', 'picture_path']
    );

    if ($wordTextColumn !== null && $wordImageColumn !== null) {
        $conditions = [
            "`{$wordImageColumn}` IS NOT NULL",
            "TRIM(`{$wordImageColumn}`) <> ''",
        ];

        if (isset($wordColumns['status'])) {
            $conditions[] = "`status` = 'active'";
        }

        $wordRows = $pdo->query(
            "SELECT
                `{$wordTextColumn}` AS word_text,
                `{$wordImageColumn}` AS image_path
             FROM words
             WHERE " . implode(' AND ', $conditions)
        )->fetchAll(PDO::FETCH_ASSOC);

        foreach ($wordRows as $wordRow) {
            $wordText = trim((string)$wordRow['word_text']);
            $imagePath = trim((string)$wordRow['image_path']);

            if ($wordText === '' || $imagePath === '') {
                continue;
            }

            $wordImageMap[] = [
                'word' => $wordText,
                'image' => $imagePath,
                'length' => mb_strlen($wordText),
            ];
        }

        usort(
            $wordImageMap,
            static fn(array $left, array $right): int =>
                $right['length'] <=> $left['length']
        );
    }
}

foreach ($sentences as &$sentence) {
    $sentence['resolved_image_path'] = trim(
        (string)($sentence['image_path'] ?? '')
    );

    if ($sentence['resolved_image_path'] !== '') {
        continue;
    }

    foreach ($wordImageMap as $wordImage) {
        if (
            ssdv2ContainsWholeWord(
                (string)$sentence['sentence_text'],
                (string)$wordImage['word']
            )
        ) {
            $sentence['resolved_image_path'] = (string)$wordImage['image'];
            break;
        }
    }
}
unset($sentence);

$sentencesById = [];

foreach ($sentences as $sentence) {
    $sentencesById[(int)$sentence['id']] = $sentence;
}

$units = [];

if ($unitIdColumn !== null && ssdv2TableExists($pdo, 'units')) {
    $unitColumns = ssdv2Columns($pdo, 'units');
    $unitNumberColumn = ssdv2FirstColumn(
        $unitColumns,
        ['unit_number', 'number', 'sort_order']
    );
    $unitTitleColumn = ssdv2FirstColumn(
        $unitColumns,
        ['title', 'name']
    );

    if ($unitTitleColumn !== null) {
        $numberSelect = $unitNumberColumn !== null
            ? "`{$unitNumberColumn}` AS unit_number"
            : 'id AS unit_number';

        $units = $pdo->query(
            "SELECT
                id,
                {$numberSelect},
                `{$unitTitleColumn}` AS title
             FROM units
             ORDER BY id"
        )->fetchAll(PDO::FETCH_ASSOC);
    }
}

ob_start();
?>

<style>
.ssdv2-page{display:grid;gap:18px}
.ssdv2-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}
.ssdv2-kicker{display:block;color:#7c3aed;font-size:12px;font-weight:850;letter-spacing:.09em;text-transform:uppercase}
.ssdv2-head h2{margin:4px 0 0;color:#0f172a;font-size:28px}
.ssdv2-subtitle{margin:7px 0 0;color:#64748b;font-size:14px}
.ssdv2-card{padding:20px;border:1px solid #e5e7eb;border-radius:18px;background:#fff}
.ssdv2-error{padding:12px 15px;border:1px solid #fecaca;border-radius:12px;background:#fef2f2;color:#991b1b;font-weight:700}
.ssdv2-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.ssdv2-field{display:grid;gap:7px}
.ssdv2-full{grid-column:1/-1}
.ssdv2-field span{color:#334155;font-size:13px;font-weight:750}
.ssdv2-input,.ssdv2-select,.ssdv2-textarea{width:100%;min-height:44px;padding:0 12px;border:1px solid #dbe2ea;border-radius:10px;background:#fff;color:#0f172a;font:inherit}
.ssdv2-textarea{min-height:92px;padding-top:10px;resize:vertical}
.ssdv2-builder{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px;margin-top:18px}
.ssdv2-panel{overflow:hidden;border:1px solid #e5e7eb;border-radius:16px;background:#fff}
.ssdv2-panel-head{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:13px 14px;border-bottom:1px solid #e5e7eb;background:#f8fafc}
.ssdv2-panel-head strong{color:#0f172a}
.ssdv2-count{display:inline-flex;padding:4px 8px;border-radius:999px;background:#eef2ff;color:#4338ca;font-size:11px;font-weight:800}
.ssdv2-search{margin:12px;width:calc(100% - 24px)}
.ssdv2-list{max-height:520px;overflow:auto;padding:0 12px 12px}
.ssdv2-item{display:grid;grid-template-columns:62px minmax(0,1fr) auto;gap:10px;align-items:center;padding:10px;margin-top:8px;border:1px solid #e5e7eb;border-radius:12px;background:#fff}
.ssdv2-item.is-selected{border-color:#93c5fd;background:#eff6ff}
.ssdv2-thumb{width:62px;height:54px;display:grid;place-items:center;overflow:hidden;border:1px solid #dbe2ea;border-radius:10px;background:#f8fafc;color:#94a3b8}
.ssdv2-thumb img{width:100%;height:100%;object-fit:contain}
.ssdv2-sentence{color:#0f172a;font-weight:800;line-height:1.4}
.ssdv2-ipa{display:block;margin-top:4px;color:#64748b;font-size:11px;font-style:italic;font-weight:500}
.ssdv2-meaning{display:block;margin-top:4px;color:#64748b;font-size:12px;line-height:1.4}
.ssdv2-item-actions{display:flex;gap:6px}
.ssdv2-icon{width:34px;height:34px;display:grid;place-items:center;border:1px solid #dbe2ea;border-radius:9px;background:#fff;cursor:pointer}
.ssdv2-add{color:#1d4ed8}
.ssdv2-selected-list{max-height:577px;overflow:auto;padding:12px}
.ssdv2-selected-item{display:grid;grid-template-columns:34px 54px minmax(0,1fr) auto;gap:9px;align-items:center;padding:9px;margin-bottom:8px;border:1px solid #e5e7eb;border-radius:12px;background:#fff}
.ssdv2-order{width:30px;height:30px;display:grid;place-items:center;border-radius:8px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:850}
.ssdv2-selected-thumb{width:54px;height:48px;display:grid;place-items:center;overflow:hidden;border:1px solid #dbe2ea;border-radius:9px;background:#f8fafc}
.ssdv2-selected-thumb img{width:100%;height:100%;object-fit:contain}
.ssdv2-selected-text{color:#0f172a;font-size:13px;font-weight:800;line-height:1.35}
.ssdv2-controls{display:flex;gap:5px;flex-wrap:wrap;justify-content:flex-end}
.ssdv2-empty{padding:48px 20px;text-align:center;color:#64748b}
.ssdv2-actions{display:flex;justify-content:flex-end;gap:9px;margin-top:18px}
.ssdv2-help{margin-top:14px;padding:12px 14px;border:1px solid #dbeafe;border-radius:12px;background:#eff6ff;color:#1d4ed8;font-size:12px;line-height:1.55}
@media(max-width:900px){
  .ssdv2-builder{grid-template-columns:1fr}
}
@media(max-width:680px){
  .ssdv2-head{flex-direction:column}
  .ssdv2-grid{grid-template-columns:1fr}
  .ssdv2-full{grid-column:auto}
}
</style>

<div class="ssdv2-page">
    <div class="ssdv2-head">
        <div>
            <span class="ssdv2-kicker">Sentence Sets</span>
            <h2><?= $isEdit ? 'Edit Sentence Set' : 'New Sentence Set' ?></h2>
            <p class="ssdv2-subtitle">
                Select sentences, listen, preview images and arrange the practice order.
            </p>
        </div>

        <a class="button button-secondary" href="index.php">
            ← Sentence Sets
        </a>
    </div>

    <?php if ($error !== ''): ?>
        <div class="ssdv2-error">
            <?= htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?>
        </div>
    <?php endif; ?>

    <form method="post" class="ssdv2-card" id="sentenceSetForm">
        <input type="hidden" name="id" value="<?= (int)$id ?>">

        <div id="selectedInputs"></div>

        <div class="ssdv2-grid">
            <label class="ssdv2-field">
                <span>Set Title *</span>
                <input
                    class="ssdv2-input"
                    type="text"
                    name="title"
                    maxlength="255"
                    required
                    value="<?= htmlspecialchars($form['title'], ENT_QUOTES, 'UTF-8') ?>"
                    placeholder="Example: Lesson 1 Speaking"
                >
            </label>

            <?php if ($statusColumn !== null): ?>
                <label class="ssdv2-field">
                    <span>Status</span>
                    <select class="ssdv2-select" name="status">
                        <option value="active" <?= $form['status'] === 'active' ? 'selected' : '' ?>>
                            Active
                        </option>
                        <option value="inactive" <?= $form['status'] === 'inactive' ? 'selected' : '' ?>>
                            Inactive
                        </option>
                    </select>
                </label>
            <?php endif; ?>

            <?php if ($unitIdColumn !== null): ?>
                <label class="ssdv2-field">
                    <span>Unit</span>
                    <select class="ssdv2-select" name="unit_id">
                        <option value="0">No specific unit</option>

                        <?php foreach ($units as $unit): ?>
                            <option
                                value="<?= (int)$unit['id'] ?>"
                                <?= (int)$form['unit_id'] === (int)$unit['id']
                                    ? 'selected'
                                    : '' ?>
                            >
                                <?= htmlspecialchars(
                                    trim(
                                        (string)$unit['unit_number']
                                        . ' - '
                                        . (string)$unit['title']
                                    ),
                                    ENT_QUOTES,
                                    'UTF-8'
                                ) ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </label>
            <?php endif; ?>

            <?php if ($setSortColumn !== null): ?>
                <label class="ssdv2-field">
                    <span>Sort Order</span>
                    <input
                        class="ssdv2-input"
                        type="number"
                        name="sort_order"
                        min="0"
                        value="<?= (int)$form['sort_order'] ?>"
                    >
                </label>
            <?php endif; ?>

            <?php if ($descriptionColumn !== null): ?>
                <label class="ssdv2-field ssdv2-full">
                    <span>Description</span>
                    <textarea
                        class="ssdv2-textarea"
                        name="description"
                        placeholder="Optional note for teachers."
                    ><?= htmlspecialchars($form['description'], ENT_QUOTES, 'UTF-8') ?></textarea>
                </label>
            <?php endif; ?>
        </div>

        <div class="ssdv2-builder">
            <section class="ssdv2-panel">
                <div class="ssdv2-panel-head">
                    <strong>Available Sentences</strong>
                    <span class="ssdv2-count" id="availableCount">
                        <?= count($sentences) ?> available
                    </span>
                </div>

                <input
                    class="ssdv2-input ssdv2-search"
                    type="search"
                    id="sentenceSearch"
                    placeholder="Search sentence or Vietnamese meaning..."
                >

                <div class="ssdv2-list" id="availableList">
                    <?php foreach ($sentences as $sentence): ?>
                        <?php
                        $sentenceId = (int)$sentence['id'];
                        $isSelected = in_array(
                            $sentenceId,
                            $form['sentence_ids'],
                            true
                        );
                        ?>
                        <article
                            class="ssdv2-item <?= $isSelected ? 'is-selected' : '' ?>"
                            data-id="<?= $sentenceId ?>"
                            data-search="<?= htmlspecialchars(
                                mb_strtolower(
                                    (string)$sentence['sentence_text']
                                    . ' '
                                    . (string)$sentence['vietnamese_meaning']
                                ),
                                ENT_QUOTES,
                                'UTF-8'
                            ) ?>"
                        >
                            <div class="ssdv2-thumb">
                                <?php if ((string)$sentence['resolved_image_path'] !== ''): ?>
                                    <img
                                        src="<?= htmlspecialchars(
                                            ssdv2AssetUrl(
                                                (string)$sentence['resolved_image_path']
                                            ),
                                            ENT_QUOTES,
                                            'UTF-8'
                                        ) ?>"
                                        alt=""
                                    >
                                <?php else: ?>
                                    🖼️
                                <?php endif; ?>
                            </div>

                            <div>
                                <div class="ssdv2-sentence">
                                    <?= htmlspecialchars(
                                        (string)$sentence['sentence_text'],
                                        ENT_QUOTES,
                                        'UTF-8'
                                    ) ?>
                                </div>

                                <?php if ((string)$sentence['ipa'] !== ''): ?>
                                    <span class="ssdv2-ipa">
                                        <?= htmlspecialchars(
                                            (string)$sentence['ipa'],
                                            ENT_QUOTES,
                                            'UTF-8'
                                        ) ?>
                                    </span>
                                <?php endif; ?>

                                <?php if ((string)$sentence['vietnamese_meaning'] !== ''): ?>
                                    <span class="ssdv2-meaning">
                                        <?= htmlspecialchars(
                                            (string)$sentence['vietnamese_meaning'],
                                            ENT_QUOTES,
                                            'UTF-8'
                                        ) ?>
                                    </span>
                                <?php endif; ?>
                            </div>

                            <div class="ssdv2-item-actions">
                                <button
                                    class="ssdv2-icon"
                                    type="button"
                                    data-play
                                    data-audio="<?= htmlspecialchars(
                                        (string)$sentence['audio_path'] !== ''
                                            ? ssdv2AssetUrl(
                                                (string)$sentence['audio_path']
                                            )
                                            : '',
                                        ENT_QUOTES,
                                        'UTF-8'
                                    ) ?>"
                                    data-text="<?= htmlspecialchars(
                                        (string)$sentence['sentence_text'],
                                        ENT_QUOTES,
                                        'UTF-8'
                                    ) ?>"
                                    title="Listen"
                                >
                                    🔊
                                </button>

                                <button
                                    class="ssdv2-icon ssdv2-add"
                                    type="button"
                                    data-add
                                    data-id="<?= $sentenceId ?>"
                                    title="<?= $isSelected ? 'Already selected' : 'Add sentence' ?>"
                                    <?= $isSelected ? 'disabled' : '' ?>
                                >
                                    +
                                </button>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>
            </section>

            <section class="ssdv2-panel">
                <div class="ssdv2-panel-head">
                    <strong>Selected Sentences</strong>
                    <span class="ssdv2-count" id="selectedCount">
                        <?= count($form['sentence_ids']) ?> selected
                    </span>
                </div>

                <div class="ssdv2-selected-list" id="selectedList"></div>
            </section>
        </div>

        <div class="ssdv2-help">
            Sentence Sets only store references to Sentence Library records.
            Images are reused from Word Library where available. The order shown
            in the Selected Sentences panel is the student practice order.
        </div>

        <div class="ssdv2-actions">
            <a class="button button-secondary" href="index.php">Cancel</a>
            <button class="button button-primary" type="submit">
                <?= $isEdit ? 'Save Changes' : 'Create Sentence Set' ?>
            </button>
        </div>
    </form>
</div>

<script>
(function () {
    var sentenceData = <?= json_encode(
        array_values(
            array_map(
                static function (array $sentence): array {
                    return [
                        'id' => (int)$sentence['id'],
                        'text' => (string)$sentence['sentence_text'],
                        'meaning' => (string)$sentence['vietnamese_meaning'],
                        'ipa' => (string)$sentence['ipa'],
                        'image' => (string)$sentence['resolved_image_path'] !== ''
                            ? ssdv2AssetUrl(
                                (string)$sentence['resolved_image_path']
                            )
                            : '',
                        'audio' => (string)$sentence['audio_path'] !== ''
                            ? ssdv2AssetUrl((string)$sentence['audio_path'])
                            : '',
                    ];
                },
                $sentences
            )
        ),
        JSON_UNESCAPED_UNICODE
        | JSON_UNESCAPED_SLASHES
        | JSON_HEX_TAG
        | JSON_HEX_APOS
        | JSON_HEX_AMP
        | JSON_HEX_QUOT
    ) ?>;

    var selectedIds = <?= json_encode(
        array_values($form['sentence_ids']),
        JSON_UNESCAPED_UNICODE
    ) ?>;

    var sentenceMap = new Map(
        sentenceData.map(function (sentence) {
            return [Number(sentence.id), sentence];
        })
    );

    var availableList = document.getElementById('availableList');
    var selectedList = document.getElementById('selectedList');
    var selectedInputs = document.getElementById('selectedInputs');
    var selectedCount = document.getElementById('selectedCount');
    var search = document.getElementById('sentenceSearch');
    var form = document.getElementById('sentenceSetForm');
    var activeAudio = null;

    function stopAudio() {
        if (activeAudio) {
            activeAudio.pause();
            activeAudio.currentTime = 0;
            activeAudio = null;
        }

        if ('speechSynthesis' in window) {
            window.speechSynthesis.cancel();
        }
    }

    function playSentence(audio, text) {
        stopAudio();

        if (audio) {
            activeAudio = new Audio(audio);
            activeAudio.play().catch(function () {});
            return;
        }

        if (!('speechSynthesis' in window) || !text) {
            return;
        }

        var utterance = new SpeechSynthesisUtterance(text);
        utterance.lang = 'en-US';
        utterance.rate = 0.82;
        utterance.pitch = 1;

        var voices = window.speechSynthesis.getVoices();
        var preferredVoice = voices.find(function (voice) {
            return /^en-US$/i.test(voice.lang);
        }) || voices.find(function (voice) {
            return /^en/i.test(voice.lang);
        });

        if (preferredVoice) {
            utterance.voice = preferredVoice;
        }

        window.speechSynthesis.speak(utterance);
    }

    function escapeHtml(value) {
        return String(value || '')
            .replaceAll('&', '&amp;')
            .replaceAll('<', '&lt;')
            .replaceAll('>', '&gt;')
            .replaceAll('"', '&quot;')
            .replaceAll("'", '&#039;');
    }

    function renderSelected() {
        selectedList.innerHTML = '';
        selectedInputs.innerHTML = '';

        if (selectedIds.length === 0) {
            selectedList.innerHTML =
                '<div class="ssdv2-empty">'
                + '<strong>No sentences selected</strong><br>'
                + 'Choose sentences from the left panel.'
                + '</div>';
        }

        selectedIds.forEach(function (id, index) {
            var sentence = sentenceMap.get(Number(id));

            if (!sentence) {
                return;
            }

            var item = document.createElement('article');
            item.className = 'ssdv2-selected-item';
            item.dataset.id = String(id);

            item.innerHTML =
                '<div class="ssdv2-order">' + (index + 1) + '</div>'
                + '<div class="ssdv2-selected-thumb">'
                + (
                    sentence.image
                        ? '<img src="' + escapeHtml(sentence.image) + '" alt="">'
                        : '🖼️'
                )
                + '</div>'
                + '<div>'
                + '<div class="ssdv2-selected-text">'
                + escapeHtml(sentence.text)
                + '</div>'
                + (
                    sentence.meaning
                        ? '<span class="ssdv2-meaning">'
                          + escapeHtml(sentence.meaning)
                          + '</span>'
                        : ''
                )
                + '</div>'
                + '<div class="ssdv2-controls">'
                + '<button class="ssdv2-icon" type="button" data-selected-play title="Listen">🔊</button>'
                + '<button class="ssdv2-icon" type="button" data-up title="Move up">↑</button>'
                + '<button class="ssdv2-icon" type="button" data-down title="Move down">↓</button>'
                + '<button class="ssdv2-icon" type="button" data-remove title="Remove">×</button>'
                + '</div>';

            selectedList.appendChild(item);

            var hidden = document.createElement('input');
            hidden.type = 'hidden';
            hidden.name = 'sentence_ids[]';
            hidden.value = String(id);
            selectedInputs.appendChild(hidden);
        });

        if (selectedCount) {
            selectedCount.textContent = selectedIds.length + ' selected';
        }

        document.querySelectorAll('[data-add]').forEach(function (button) {
            var id = Number(button.dataset.id);
            var selected = selectedIds.includes(id);

            button.disabled = selected;
            button.title = selected ? 'Already selected' : 'Add sentence';

            var card = button.closest('.ssdv2-item');

            if (card) {
                card.classList.toggle('is-selected', selected);
            }
        });
    }

    document.addEventListener('click', function (event) {
        var addButton = event.target.closest('[data-add]');

        if (addButton) {
            var addId = Number(addButton.dataset.id);

            if (!selectedIds.includes(addId)) {
                selectedIds.push(addId);
                renderSelected();
            }

            return;
        }

        var playButton = event.target.closest('[data-play]');

        if (playButton) {
            playSentence(
                String(playButton.dataset.audio || ''),
                String(playButton.dataset.text || '')
            );
            return;
        }

        var selectedItem = event.target.closest('.ssdv2-selected-item');

        if (!selectedItem) {
            return;
        }

        var id = Number(selectedItem.dataset.id);
        var index = selectedIds.indexOf(id);

        if (index < 0) {
            return;
        }

        if (event.target.closest('[data-selected-play]')) {
            var sentence = sentenceMap.get(id);

            if (sentence) {
                playSentence(sentence.audio, sentence.text);
            }

            return;
        }

        if (event.target.closest('[data-up]') && index > 0) {
            var previous = selectedIds[index - 1];
            selectedIds[index - 1] = selectedIds[index];
            selectedIds[index] = previous;
            renderSelected();
            return;
        }

        if (
            event.target.closest('[data-down]')
            && index < selectedIds.length - 1
        ) {
            var next = selectedIds[index + 1];
            selectedIds[index + 1] = selectedIds[index];
            selectedIds[index] = next;
            renderSelected();
            return;
        }

        if (event.target.closest('[data-remove]')) {
            selectedIds.splice(index, 1);
            renderSelected();
        }
    });

    if (search && availableList) {
        search.addEventListener('input', function () {
            var query = String(search.value || '').trim().toLowerCase();

            availableList
                .querySelectorAll('.ssdv2-item')
                .forEach(function (item) {
                    var haystack = String(item.dataset.search || '');

                    item.style.display =
                        query === '' || haystack.includes(query)
                            ? 'grid'
                            : 'none';
                });
        });
    }

    if (form) {
        form.addEventListener('submit', function (event) {
            if (selectedIds.length === 0) {
                event.preventDefault();
                alert('Please select at least one sentence.');
            }
        });
    }

    if ('speechSynthesis' in window) {
        window.speechSynthesis.getVoices();
        window.speechSynthesis.onvoiceschanged = function () {
            window.speechSynthesis.getVoices();
        };
    }

    renderSelected();
})();
</script>

<?php
$content = ob_get_clean();
require __DIR__ . '/../layouts/app.php';
