<?php

require __DIR__ . '/../bootstrap.php';

use KeyLair\Auth;
use KeyLair\Csrf;
use KeyLair\Database;
use KeyLair\Helpers;
use KeyLair\I18n;
use KeyLair\ImageUpload;
use KeyLair\AuditLog;
use KeyLair\PageStyle;
use KeyLair\Platform;
use KeyLair\ProductPlatform;
use KeyLair\Settings;

Auth::requireEditAccess();
$admin = Auth::user();
$pdo = Database::connection();

$uploadDir = ROOT_PATH . '/public/uploads/products';

$productId = isset($_GET['id']) ? (int) $_GET['id'] : (isset($_POST['id']) ? (int) $_POST['id'] : 0);
$product = null;
if ($productId > 0) {
    $stmt = $pdo->prepare('SELECT * FROM products WHERE id = :id');
    $stmt->execute(['id' => $productId]);
    $product = $stmt->fetch();
    if (!$product) {
        http_response_code(404);
        die(I18n::t('product_form.product_not_found'));
    }
}

$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    Csrf::requireValid();
    $action = $_POST['form_action'] ?? 'save';

    if ($action === 'delete_media') {
        $mediaId = (int) ($_POST['media_id'] ?? 0);
        $stmt = $pdo->prepare('SELECT * FROM product_media WHERE id = :id AND product_id = :pid');
        $stmt->execute(['id' => $mediaId, 'pid' => $productId]);
        $media = $stmt->fetch();
        if ($media) {
            $pdo->prepare('DELETE FROM product_media WHERE id = :id')->execute(['id' => $mediaId]);
            if ($media['type'] === 'screenshot') {
                @unlink($uploadDir . '/' . $media['value']);
            }
        }
        Helpers::redirect('product_form.php?id=' . $productId);
    }

    if ($action === 'delete_cover_image') {
        $stmt = $pdo->prepare('SELECT cover_image_path FROM products WHERE id = :id');
        $stmt->execute(['id' => $productId]);
        $oldPath = $stmt->fetchColumn();
        if ($oldPath) {
            $pdo->prepare('UPDATE products SET cover_image_path = NULL WHERE id = :id')->execute(['id' => $productId]);
            @unlink($uploadDir . '/' . $oldPath);
        }
        Helpers::redirect('product_form.php?id=' . $productId);
    }

    if ($action === 'delete_background_image') {
        $stmt = $pdo->prepare('SELECT background_image_path FROM products WHERE id = :id');
        $stmt->execute(['id' => $productId]);
        $oldPath = $stmt->fetchColumn();
        if ($oldPath) {
            $pdo->prepare('UPDATE products SET background_image_path = NULL WHERE id = :id')->execute(['id' => $productId]);
            @unlink(ROOT_PATH . '/public' . $oldPath);
        }
        Helpers::redirect('product_form.php?id=' . $productId);
    }

    if ($action === 'save') {
        $name = trim($_POST['name'] ?? '');
        $slug = trim($_POST['slug'] ?? '') ?: Helpers::slugify($name);
        $slug = Helpers::slugify($slug);
        $status = in_array($_POST['status'] ?? '', ['draft', 'active', 'archived'], true) ? $_POST['status'] : 'draft';
        $introText = Helpers::renderRichText(trim($_POST['intro_text'] ?? ''));
        $outroText = Helpers::renderRichText(trim($_POST['outro_text'] ?? ''));
        $youtubeUrls = array_filter(array_map('trim', explode("\n", $_POST['youtube_urls'] ?? '')));
        $defaultMaxClaimsRaw = trim($_POST['default_max_claims'] ?? '');
        $defaultMaxClaims = $defaultMaxClaimsRaw !== '' ? max(1, (int) $defaultMaxClaimsRaw) : null;
        $customCssRaw = trim($_POST['custom_css'] ?? '');
        $customCss = null;
        if ($customCssRaw !== '') {
            $cssCheck = PageStyle::validateInlineCss($customCssRaw);
            if ($cssCheck['ok']) {
                $customCss = $customCssRaw;
            } else {
                $errors[] = I18n::t('product_form.errors.custom_css_prefix') . $cssCheck['error'];
            }
        }
        $themeRaw = trim($_POST['theme'] ?? '');
        $productTheme = ($themeRaw !== '' && in_array($themeRaw, Settings::THEMES, true)) ? $themeRaw : null;

        if ($name === '') {
            $errors[] = I18n::t('product_form.errors.name_required');
        }

        // Slug uniqueness check
        if (!$errors) {
            $check = $pdo->prepare('SELECT id FROM products WHERE slug = :slug AND id != :id');
            $check->execute(['slug' => $slug, 'id' => $productId]);
            if ($check->fetch()) {
                $slug .= '-' . substr(bin2hex(random_bytes(2)), 0, 4);
            }
        }

        if (!$errors) {
            if ($productId > 0) {
                $stmt = $pdo->prepare(
                    'UPDATE products SET name=:name, slug=:slug, status=:status, intro_text=:intro, outro_text=:outro, default_max_claims=:default_max_claims, custom_css=:custom_css, theme=:theme
                     WHERE id=:id'
                );
                $stmt->execute([
                    'name' => $name, 'slug' => $slug, 'status' => $status,
                    'intro' => $introText, 'outro' => $outroText, 'default_max_claims' => $defaultMaxClaims,
                    'custom_css' => $customCss, 'theme' => $productTheme, 'id' => $productId,
                ]);
                AuditLog::log($admin['id'], 'product_updated', $name);
            } else {
                $stmt = $pdo->prepare(
                    'INSERT INTO products (name, slug, status, intro_text, outro_text, default_max_claims, custom_css, theme, created_at)
                     VALUES (:name,:slug,:status,:intro,:outro,:default_max_claims,:custom_css,:theme,NOW())'
                );
                $stmt->execute([
                    'name' => $name, 'slug' => $slug, 'status' => $status,
                    'intro' => $introText, 'outro' => $outroText, 'default_max_claims' => $defaultMaxClaims,
                    'custom_css' => $customCss, 'theme' => $productTheme,
                ]);
                $productId = (int) $pdo->lastInsertId();
                AuditLog::log($admin['id'], 'product_created', $name);
            }

            // Background image (optional replace) -- only meaningful once this
            // product's own theme is set to Custom, but stored regardless so
            // switching to Custom later doesn't lose a previously-chosen image.
            if (!empty($_FILES['background_image']) && $_FILES['background_image']['error'] !== UPLOAD_ERR_NO_FILE) {
                $result = ImageUpload::save($_FILES['background_image'], $uploadDir);
                if ($result['ok']) {
                    $old = $pdo->prepare('SELECT background_image_path FROM products WHERE id = :id');
                    $old->execute(['id' => $productId]);
                    $oldPath = $old->fetchColumn();
                    $pdo->prepare('UPDATE products SET background_image_path = :path WHERE id = :id')
                        ->execute(['path' => '/uploads/products/' . $result['filename'], 'id' => $productId]);
                    if ($oldPath) {
                        @unlink(ROOT_PATH . '/public' . $oldPath);
                    }
                } else {
                    $errors[] = I18n::t('product_form.errors.background_image_prefix') . $result['error'];
                }
            }

            // Cover image (optional replace)
            if (!empty($_FILES['cover_image']) && $_FILES['cover_image']['error'] !== UPLOAD_ERR_NO_FILE) {
                $result = ImageUpload::save($_FILES['cover_image'], $uploadDir);
                if ($result['ok']) {
                    $old = $pdo->prepare('SELECT cover_image_path FROM products WHERE id = :id');
                    $old->execute(['id' => $productId]);
                    $oldPath = $old->fetchColumn();
                    $pdo->prepare('UPDATE products SET cover_image_path = :path WHERE id = :id')
                        ->execute(['path' => $result['filename'], 'id' => $productId]);
                    if ($oldPath) {
                        @unlink($uploadDir . '/' . $oldPath);
                    }
                } else {
                    $errors[] = I18n::t('product_form.errors.cover_image_prefix') . $result['error'];
                }
            }

            // New screenshots (append, keep existing order)
            if (!empty($_FILES['screenshots']) && is_array($_FILES['screenshots']['name'])) {
                $maxOrderStmt = $pdo->prepare('SELECT COALESCE(MAX(sort_order), -1) FROM product_media WHERE product_id = :pid');
                $maxOrderStmt->execute(['pid' => $productId]);
                $nextOrder = (int) $maxOrderStmt->fetchColumn() + 1;

                $count = count($_FILES['screenshots']['name']);
                for ($i = 0; $i < $count; $i++) {
                    if ($_FILES['screenshots']['error'][$i] === UPLOAD_ERR_NO_FILE) {
                        continue;
                    }
                    $singleFile = [
                        'name' => $_FILES['screenshots']['name'][$i],
                        'type' => $_FILES['screenshots']['type'][$i],
                        'tmp_name' => $_FILES['screenshots']['tmp_name'][$i],
                        'error' => $_FILES['screenshots']['error'][$i],
                        'size' => $_FILES['screenshots']['size'][$i],
                    ];
                    $result = ImageUpload::save($singleFile, $uploadDir);
                    if ($result['ok']) {
                        $pdo->prepare(
                            'INSERT INTO product_media (product_id, type, value, sort_order, created_at)
                             VALUES (:pid, "screenshot", :val, :order, NOW())'
                        )->execute(['pid' => $productId, 'val' => $result['filename'], 'order' => $nextOrder]);
                        $nextOrder++;
                    } else {
                        $errors[] = sprintf(I18n::t('product_form.errors.screenshot_prefix'), $singleFile['name']) . $result['error'];
                    }
                }
            }

            // Platform restriction + per-platform claim quota (empty selection = unrestricted, same as before this existed)
            if (!empty($_POST['restrict_platforms'])) {
                $selections = [];
                $postedLimits = is_array($_POST['platform_limits'] ?? null) ? $_POST['platform_limits'] : [];
                foreach ((array) ($_POST['platforms'] ?? []) as $slug) {
                    if (!is_string($slug) || !Platform::exists($slug)) {
                        continue;
                    }
                    $rawLimit = $postedLimits[$slug] ?? '';
                    $limitRaw = is_scalar($rawLimit) ? trim((string) $rawLimit) : '';
                    $selections[$slug] = $limitRaw !== '' ? max(0, (int) $limitRaw) : null;
                }
                ProductPlatform::set($productId, $selections);
            } else {
                ProductPlatform::set($productId, []);
            }

            // YouTube links: replace the full set each save (simple textarea, one URL per line)
            $pdo->prepare('DELETE FROM product_media WHERE product_id = :pid AND type = "youtube"')->execute(['pid' => $productId]);
            $order = 1000; // keep videos after screenshots in default sort unless admin reorders later
            foreach ($youtubeUrls as $url) {
                if (Helpers::youtubeEmbedUrl($url)) {
                    $pdo->prepare(
                        'INSERT INTO product_media (product_id, type, value, sort_order, created_at) VALUES (:pid, "youtube", :val, :order, NOW())'
                    )->execute(['pid' => $productId, 'val' => $url, 'order' => $order]);
                    $order++;
                }
            }

            if (empty($errors)) {
                Helpers::redirect('product_form.php?id=' . $productId . '&saved=1');
            }
        }

        // Reload product for redisplay with errors
        $stmt = $pdo->prepare('SELECT * FROM products WHERE id = :id');
        $stmt->execute(['id' => $productId]);
        $product = $stmt->fetch();
    }
}

$screenshots = [];
$youtubeLinks = [];
$platformLimits = [];
$platformsRestricted = false;
if ($productId > 0) {
    $platformLimits = ProductPlatform::forProduct($productId);
    $platformsRestricted = !empty($platformLimits);
    $mediaStmt = $pdo->prepare('SELECT * FROM product_media WHERE product_id = :pid ORDER BY sort_order ASC, id ASC');
    $mediaStmt->execute(['pid' => $productId]);
    foreach ($mediaStmt->fetchAll() as $m) {
        if ($m['type'] === 'screenshot') {
            $screenshots[] = $m;
        } else {
            $youtubeLinks[] = $m['value'];
        }
    }
}

$pageTitle = $product ? I18n::t('product_form.page_title_edit') : I18n::t('product_form.page_title_new');
$activeNav = 'products';
$extraAdminCss = 'admin-product-editor';
require __DIR__ . '/includes/layout_header.php';
?>
<div class="topbar">
  <h1><?= $product ? Helpers::e(I18n::t('product_form.page_title_edit')) : Helpers::e(I18n::t('product_form.page_title_new')) ?></h1>
  <?php if ($product): ?>
  <div class="topbar-status-row" style="display:flex; align-items:center; gap:10px;">
    <span class="status-pill"><?= Helpers::e(I18n::t('product_form.status_' . $product['status'])) ?></span>
    <button type="button" onclick="kvOpenLivePreview();" class="campaign-select" style="color:var(--text-muted);"><?= Helpers::e(I18n::t('product_form.preview_claim_page')) ?></button>
  </div>
  <?php endif; ?>
</div>

<?php if (!empty($errors)): ?>
  <div class="form-section" style="border-color:var(--danger); margin-bottom:16px;">
    <?php foreach ($errors as $err): ?><p style="color:var(--danger); font-size:13px; margin:0;"><?= Helpers::e($err) ?></p><?php endforeach; ?>
  </div>
<?php elseif (!empty($_GET['saved'])): ?>
  <div class="form-section" style="border-color:var(--signal-dim); margin-bottom:16px;">
    <p style="color:var(--signal); font-size:13px; margin:0;"><?= Helpers::e(I18n::t('product_form.flash.saved')) ?></p>
  </div>
<?php endif; ?>

<form method="post" enctype="multipart/form-data" class="form-shell">
  <?= Csrf::field() ?>
  <input type="hidden" name="form_action" value="save">
  <input type="hidden" name="id" value="<?= (int) $productId ?>">

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_basics_title')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_basics_hint')) ?></p>
    <div class="field-row">
      <div class="field">
        <label><?= Helpers::e(I18n::t('product_form.field_product_name')) ?></label>
        <input type="text" name="name" value="<?= Helpers::e($product['name'] ?? '') ?>" required>
      </div>
      <div class="field">
        <label><?= Helpers::e(I18n::t('product_form.field_slug')) ?></label>
        <input type="text" name="slug" value="<?= Helpers::e($product['slug'] ?? '') ?>" placeholder="<?= Helpers::e(I18n::t('product_form.slug_placeholder')) ?>">
      </div>
    </div>
    <div class="field-row">
      <div class="field">
        <label><?= Helpers::e(I18n::t('product_form.field_status')) ?></label>
        <select name="status">
          <option value="draft" <?= (!$product || $product['status'] === 'draft') ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.status_draft')) ?></option>
          <option value="active" <?= ($product && $product['status'] === 'active') ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.status_active')) ?></option>
          <option value="archived" <?= ($product && $product['status'] === 'archived') ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.status_archived')) ?></option>
        </select>
      </div>
      <div class="field">
        <label><?= Helpers::e(I18n::t('product_form.field_default_max_claims')) ?></label>
        <input type="number" min="1" name="default_max_claims" placeholder="<?= Helpers::e(I18n::t('product_form.default_max_claims_placeholder')) ?>" value="<?= isset($product['default_max_claims']) && $product['default_max_claims'] !== null ? (int) $product['default_max_claims'] : '' ?>">
      </div>
    </div>
  </div>

  <details class="form-section" open>
    <summary class="form-section-title" style="cursor:pointer;"><?= Helpers::e(I18n::t('product_form.section_platforms_title')) ?></summary>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_platforms_hint')) ?></p>
    <div class="field">
      <label style="display:flex; align-items:center; gap:8px; font-weight:500;">
        <input type="checkbox" name="restrict_platforms" value="1" id="restrict-platforms-toggle" <?= $platformsRestricted ? 'checked' : '' ?> onchange="document.getElementById('platform-selection-list').style.display = this.checked ? 'block' : 'none';">
        <?= Helpers::e(I18n::t('product_form.restrict_platforms_label')) ?>
      </label>
    </div>
    <div id="platform-selection-list" style="display:<?= $platformsRestricted ? 'block' : 'none' ?>; margin-top:8px;">
      <?php if (empty(Platform::all())): ?>
        <p style="color:var(--text-faint); font-size:12.5px;"><?= Helpers::e(I18n::t('product_form.no_platforms_configured')) ?></p>
      <?php else: ?>
      <div style="display:flex; gap:14px; margin-bottom:10px;">
        <button type="button" onclick="document.querySelectorAll('#platform-selection-list input[name=\'platforms[]\']').forEach(function(cb){cb.checked = true;});" style="background:none; border:none; color:var(--signal); font-size:12px; cursor:pointer; padding:0;"><?= Helpers::e(I18n::t('product_form.select_all')) ?></button>
        <button type="button" onclick="document.querySelectorAll('#platform-selection-list input[name=\'platforms[]\']').forEach(function(cb){cb.checked = false;});" style="background:none; border:none; color:var(--text-muted); font-size:12px; cursor:pointer; padding:0;"><?= Helpers::e(I18n::t('product_form.deselect_all')) ?></button>
      </div>
      <?php foreach (Platform::all() as $p): $slug = $p['slug']; $selected = array_key_exists($slug, $platformLimits); $limit = $platformLimits[$slug] ?? null; ?>
      <div class="field-row" style="align-items:center; margin-bottom:6px;">
        <label style="display:flex; align-items:center; gap:8px; flex:1; font-weight:400;">
          <input type="checkbox" name="platforms[]" value="<?= Helpers::e($slug) ?>" <?= $selected ? 'checked' : '' ?>>
          <?= Helpers::e($p['label']) ?>
        </label>
        <input type="number" min="0" name="platform_limits[<?= Helpers::e($slug) ?>]" placeholder="<?= Helpers::e(I18n::t('product_form.unlimited_placeholder')) ?>" value="<?= $limit !== null ? (int) $limit : '' ?>" class="platform-limit-input" style="width:130px;">
      </div>
      <?php endforeach; endif; ?>
    </div>
  </details>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_cover_title')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_cover_hint')) ?></p>
    <?php if (!empty($product['cover_image_path'])): ?>
      <div style="position:relative; width:100%; aspect-ratio:16/9; border-radius:12px; overflow:hidden; border:1px solid var(--line);">
        <img src="/uploads/products/<?= Helpers::e($product['cover_image_path']) ?>" alt="" style="width:100%;height:100%;object-fit:cover;">
        <button type="button" onclick="if(confirm(<?= json_encode(I18n::t('product_form.remove_cover_confirm_js'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>)) document.getElementById('cover-delete-form').submit();" style="position:absolute; top:8px; right:8px; width:26px;height:26px; border-radius:50%; background:rgba(11,14,20,0.8); border:none; color:#fff; font-size:13px; cursor:pointer;">&times;</button>
      </div>
    <?php else: ?>
      <label class="cover-upload" style="cursor:pointer;">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="10" r="2"/><path d="M21 16l-5.5-5.5L7 19"/></svg>
        <span id="cover-filename"><?= Helpers::e(I18n::t('product_form.cover_choose_text')) ?></span>
        <input type="file" name="cover_image" accept="image/jpeg,image/png,image/webp" style="display:none;" onchange="document.getElementById('cover-filename').textContent = this.files[0]?.name || <?= json_encode(I18n::t('product_form.cover_choose_fallback'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>;">
      </label>
    <?php endif; ?>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_intro_title')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_intro_hint')) ?></p>
    <?= rte_field('intro_text', $product['intro_text'] ?? '') ?>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_outro_title')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_outro_hint')) ?></p>
    <?= rte_field('outro_text', $product['outro_text'] ?? '') ?>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_screenshots_title')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_screenshots_hint')) ?></p>
    <?php if (!empty($screenshots)): ?>
      <div class="shot-grid" style="margin-bottom:12px;">
        <?php foreach ($screenshots as $i => $shot): ?>
          <div class="shot-slot filled" style="position:relative; overflow:hidden;">
            <img src="/uploads/products/<?= Helpers::e($shot['value']) ?>" alt="" style="width:100%;height:100%;object-fit:cover;">
            <span class="num"><?= str_pad((string) ($i + 1), 2, '0', STR_PAD_LEFT) ?></span>
            <?php if ($productId > 0): ?>
            <button type="button" onclick="if(confirm(<?= json_encode(I18n::t('product_form.remove_screenshot_confirm_js'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>)){document.getElementById('media-delete-id').value=<?= (int) $shot['id'] ?>;document.getElementById('media-delete-form').submit();}" style="position:absolute; top:4px; right:4px; width:20px;height:20px; border-radius:50%; background:rgba(11,14,20,0.8); border:none; color:#fff; font-size:11px; cursor:pointer;">&times;</button>
            <?php endif; ?>
          </div>
        <?php endforeach; ?>
      </div>
    <?php endif; ?>
    <label class="cover-upload" style="aspect-ratio:auto; padding:16px; cursor:pointer;">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="10" r="2"/><path d="M21 16l-5.5-5.5L7 19"/></svg>
      <span id="shots-filename"><?= Helpers::e(I18n::t('product_form.screenshots_choose_text')) ?></span>
      <input type="file" name="screenshots[]" accept="image/jpeg,image/png,image/webp" multiple style="display:none;" onchange="document.getElementById('shots-filename').textContent = <?= json_encode(I18n::t('product_form.files_selected'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>.replace('%d', this.files.length);">
    </label>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_youtube_title')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_youtube_hint')) ?></p>
    <textarea name="youtube_urls" rows="3" style="width:100%; background:var(--bg-void); border:1px solid var(--line); color:var(--text-primary); font-family:var(--font-mono); font-size:12.5px; padding:10px 12px; border-radius:8px;" placeholder="https://youtube.com/watch?v=..."><?= Helpers::e(implode("\n", $youtubeLinks)) ?></textarea>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_theme_title')) ?></p>
    <p class="form-section-hint">
      <?= sprintf(
        Helpers::e(I18n::t('product_form.section_theme_hint')),
        '<a href="design.php" style="color:var(--signal);">' . Helpers::e(I18n::t('product_form.design_link_text')) . '</a>'
      ) ?>
    </p>
    <?php $productThemeValue = $product['theme'] ?? ''; ?>
    <div class="field">
      <select name="theme" id="product-theme-select" onchange="document.getElementById('product-bg-section').style.opacity = this.value === 'custom' ? '1' : '0.45'; document.getElementById('product-bg-section').style.pointerEvents = this.value === 'custom' ? '' : 'none';">
        <option value="" <?= $productThemeValue === '' ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.theme_inherit')) ?></option>
        <option value="default" <?= $productThemeValue === 'default' ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.theme_default')) ?></option>
        <option value="light" <?= $productThemeValue === 'light' ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.theme_light')) ?></option>
        <option value="steam" <?= $productThemeValue === 'steam' ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.theme_steam')) ?></option>
        <option value="custom" <?= $productThemeValue === 'custom' ? 'selected' : '' ?>><?= Helpers::e(I18n::t('product_form.theme_custom')) ?></option>
      </select>
    </div>

    <div id="product-bg-section" style="margin-top:14px; <?= $productThemeValue === 'custom' ? '' : 'opacity:0.45; pointer-events:none;' ?>">
      <p class="form-section-hint"><?= Helpers::e(I18n::t('product_form.section_bg_hint')) ?></p>
      <?php $productBg = $product['background_image_path'] ?? null; ?>
      <div style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
        <?php if ($productBg): ?>
          <div style="width:140px; aspect-ratio:16/9; border-radius:10px; overflow:hidden; border:1px solid var(--line);">
            <img src="<?= Helpers::e($productBg) ?>" alt="" style="width:100%;height:100%;object-fit:cover;">
          </div>
        <?php endif; ?>
        <label class="btn btn-ghost file-choose-label" style="cursor:pointer; display:inline-flex; align-items:center; gap:8px; margin:0;">
          <span><?= Helpers::e(I18n::t('product_form.choose_file')) ?></span>
          <span id="product-bg-name" style="color:var(--text-faint); font-weight:400;"><?= Helpers::e(I18n::t('product_form.no_file_chosen')) ?></span>
          <input type="file" name="background_image" accept="image/jpeg,image/png,image/webp" style="display:none;" onchange="document.getElementById('product-bg-name').textContent = this.files[0]?.name || <?= json_encode(I18n::t('product_form.no_file_chosen'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>;">
        </label>
        <?php if ($productBg): ?>
          <button type="button" onclick="if(confirm(<?= json_encode(I18n::t('product_form.remove_bg_confirm_js'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>)) document.getElementById('background-delete-form').submit();" class="btn btn-ghost" style="color:var(--danger);"><?= Helpers::e(I18n::t('product_form.remove_button')) ?></button>
        <?php endif; ?>
      </div>
    </div>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('product_form.section_css_title')) ?></p>
    <p class="form-section-hint">
      <?= sprintf(
        Helpers::e(I18n::t('product_form.section_css_hint')),
        '<a href="design.php" style="color:var(--signal);">' . Helpers::e(I18n::t('product_form.design_link_text')) . '</a>'
      ) ?>
    </p>
    <textarea name="custom_css" rows="6" style="width:100%; background:var(--bg-void); border:1px solid var(--line); color:var(--text-primary); font-family:var(--font-mono); font-size:12.5px; padding:10px 12px; border-radius:8px;" placeholder="<?= Helpers::e(I18n::t('product_form.custom_css_placeholder_label')) ?>&#10;.hero h1 { color: #ffcc00; }"><?= Helpers::e($product['custom_css'] ?? '') ?></textarea>
  </div>

  <div class="form-actions">
    <a href="products.php" class="btn btn-ghost" style="text-decoration:none;"><?= Helpers::e(I18n::t('product_form.back_to_products')) ?></a>
    <!-- No Preview here for a brand-new, not-yet-saved product -- the
         generic mockup it used to point at was never actually related
         to whatever's typed into the form above it, which read as
         broken rather than just generic. An existing product's own
         Preview (real, built from its saved data) stays up top. -->
    <button type="submit" class="btn btn-primary"><?= Helpers::e(I18n::t('product_form.save_product')) ?></button>
  </div>
</form>

<?php if ($product): ?>
<!-- Kept outside the main form above -- nesting a <form> inside another is
     invalid HTML and made the browser close the outer form early, silently
     dropping every field after it (this is why screenshots/Save stopped
     working once a cover image existed). -->
<form id="cover-delete-form" method="post" style="display:none;">
  <?= Csrf::field() ?>
  <input type="hidden" name="form_action" value="delete_cover_image">
  <input type="hidden" name="id" value="<?= (int) $productId ?>">
</form>
<form id="media-delete-form" method="post" style="display:none;">
  <?= Csrf::field() ?>
  <input type="hidden" name="form_action" value="delete_media">
  <input type="hidden" name="id" value="<?= (int) $productId ?>">
  <input type="hidden" name="media_id" id="media-delete-id">
</form>
<form id="background-delete-form" method="post" style="display:none;">
  <?= Csrf::field() ?>
  <input type="hidden" name="form_action" value="delete_background_image">
  <input type="hidden" name="id" value="<?= (int) $productId ?>">
</form>
<!-- Opens product_preview.php in a new tab via a real POST (not just a
     link) so it can carry whatever's currently typed in the editor above
     -- including changes never saved -- rather than only ever showing
     this product's last-saved row. target="_blank" on the form itself,
     not a click-time window.open(), keeps this working the same way
     under a popup blocker as any other same-click new-tab link. -->
<form id="live-preview-form" method="post" action="product_preview.php?id=<?= (int) $productId ?>" target="_blank" style="display:none;">
  <?= Csrf::field() ?>
  <input type="hidden" name="live_preview" value="1">
  <input type="hidden" name="name">
  <input type="hidden" name="intro_text">
  <input type="hidden" name="outro_text">
  <input type="hidden" name="custom_css">
  <input type="hidden" name="theme">
</form>
<script>
function kvOpenLivePreview() {
  var form = document.getElementById('live-preview-form');
  var editorForm = document.querySelector('form.form-shell');
  form.elements['name'].value = editorForm.elements['name'].value;
  form.elements['intro_text'].value = document.getElementById('rte_intro_text_hidden').value;
  form.elements['outro_text'].value = document.getElementById('rte_outro_text_hidden').value;
  form.elements['custom_css'].value = editorForm.elements['custom_css'].value;
  form.elements['theme'].value = editorForm.elements['theme'].value;
  form.submit();
}
</script>
<?php endif; ?>

<?php
require __DIR__ . '/includes/layout_footer.php';

/**
 * A lightweight contenteditable rich-text field. Uses the browser's built-in
 * execCommand for bold/italic/link — deprecated but universally supported for
 * this simple a use case, and avoids pulling in a JS editor dependency.
 * Output is plain HTML restricted server-side to a small allow-list on display
 * (see Helpers::renderRichText), so what's typed here is never trusted as-is.
 */
/**
 * A lightweight contenteditable rich-text field. Uses the browser's built-in
 * execCommand for bold/italic/link — deprecated but universally supported for
 * this simple a use case, and avoids pulling in a JS editor dependency.
 *
 * $value here is always already-sanitized HTML (product_form.php runs every
 * submission through Helpers::renderRichText() before it's ever stored), so
 * it's safe to use directly as the editable body's content. The hidden input
 * that actually gets submitted still needs its own attribute-escaping, since
 * that's a different context (an HTML attribute, not the document body).
 */
function rte_field(string $name, string $value): string
{
    $id = 'rte_' . $name;
    $attrEscaped = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    $linkPrompt = json_encode(I18n::t('product_form.rte_link_prompt'), JSON_HEX_APOS | JSON_HEX_QUOT);
    return <<<HTML
    <div class="rte">
      <div class="rte-toolbar">
        <span class="rte-btn" onclick="document.execCommand('bold')"><b>B</b></span>
        <span class="rte-btn" onclick="document.execCommand('italic')"><i>I</i></span>
        <span class="rte-btn" onclick="var u=prompt({$linkPrompt}); if(u) document.execCommand('createLink', false, u);">🔗</span>
        <span class="rte-btn" onclick="document.execCommand('insertParagraph')">¶</span>
      </div>
      <div class="rte-body" id="{$id}" contenteditable="true" oninput="document.getElementById('{$id}_hidden').value = this.innerHTML">{$value}</div>
    </div>
    <input type="hidden" name="{$name}" id="{$id}_hidden" value="{$attrEscaped}">
    HTML;
}
