<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

// === SECURITY: Require admin login ===
// Force session cookie path = '/' so PHPSESSID stays valid whether accessed
// from /?tab=apps (root via router.php) or /inject/?tab=apps directly.
if (session_status() === PHP_SESSION_NONE) {
    $cp = session_get_cookie_params();
    session_set_cookie_params([
        'lifetime' => $cp['lifetime'] ?? 0,
        'path'     => '/',
        'domain'   => $cp['domain'] ?? '',
        'secure'   => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
        'httponly' => true,
        'samesite' => 'Lax'
    ]);
    session_name('PHPSESSID');
    session_start();
}
if (empty($_SESSION['admin_logged_in']) || empty($_SESSION['user_id'])) {
    // Redirect ke halaman login admin
    $loginUrl = 'index.php';
    header('Location: ' . $loginUrl);
    exit();
}
$adminRole = $_SESSION['admin_role'] ?? '';
$adminName = $_SESSION['user_name'] ?? 'Admin';

define('DATA_DIR', __DIR__ . '/data');

function loadData($file) {
    $path = DATA_DIR . '/' . $file;
    if (!file_exists($path)) return [];
    $raw = file_get_contents($path);
    return json_decode($raw, true) ?: [];
}

$base_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
          . '://' . $_SERVER['HTTP_HOST']
          . dirname($_SERVER['REQUEST_URI']) . '/index.php';

// Load applications for feature dropdown
$applications = loadData('applications.json');
$activeApps = array_filter($applications, function($a){ return !empty($a['is_active']); });

// Load some sample members for quick test
$members = loadData('members.json');
$sampleMembers = array_slice(array_filter($members, function($m){ return !empty($m['is_active']); }), 0, 5);
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>API Dashboard - TEKNO-APPS</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"/>
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{--deep:#020c18;--blue:#0066ff;--bright:#0099ff;--light:#4db8ff;--text:#e8f4ff;--sub:#7aaed4;--muted:#4a7a9b;--glass:rgba(4,22,48,.85);--border:rgba(0,150,255,.18);--ok:#00e676;--err:#ff4d4d;--warn:#ffaa00;--code:#1a2438}
body{min-height:100vh;background:var(--deep);font-family:"Inter",sans-serif;color:var(--text)}
body::before{content:"";position:fixed;inset:0;pointer-events:none;background:radial-gradient(ellipse at 15% 15%,rgba(0,80,180,.22) 0%,transparent 55%),radial-gradient(ellipse at 85% 85%,rgba(0,40,130,.16) 0%,transparent 55%);z-index:0}
.wrap{max-width:1200px;margin:0 auto;padding:28px 18px;position:relative;z-index:1}
.hdr{display:flex;align-items:center;gap:14px;margin-bottom:22px}
.logo{width:46px;height:46px;border-radius:13px;background:linear-gradient(135deg,#0044cc,#0099ff);display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:900;box-shadow:0 0 18px rgba(0,150,255,.4)}
.hdr-text h1{font-size:20px;font-weight:800;background:linear-gradient(135deg,#e0f0ff,#4db8ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.hdr-text p{font-size:12px;color:var(--sub);margin-top:3px}
.tabs{display:flex;gap:4px;margin-bottom:16px;border-bottom:1px solid var(--border);overflow-x:auto}
.tab{padding:10px 18px;font-size:13px;font-weight:600;color:var(--sub);cursor:pointer;border:none;background:none;border-bottom:2px solid transparent;font-family:inherit;white-space:nowrap}
.tab.active{color:#fff;border-bottom-color:var(--bright)}
.tab:hover{color:var(--light)}
.tab-content{display:none}
.tab-content.active{display:block}
.card{background:var(--glass);border:1px solid var(--border);border-radius:12px;padding:18px;margin-bottom:14px;backdrop-filter:blur(10px)}
.ct{font-size:14px;font-weight:700;margin-bottom:14px;color:#fff;display:flex;align-items:center;gap:8px}
.ct::before{content:"";width:4px;height:14px;background:var(--bright);border-radius:2px}
.endpoint{background:var(--code);border:1px solid var(--border);border-radius:8px;padding:12px 14px;margin-bottom:10px;font-family:"JetBrains Mono",monospace}
.endpoint-head{display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap}
.method{font-size:11px;font-weight:800;padding:3px 8px;border-radius:4px;letter-spacing:.5px}
.method.GET{background:rgba(0,230,118,.15);color:#00e676;border:1px solid rgba(0,230,118,.3)}
.method.POST{background:rgba(255,170,0,.15);color:#ffcc44;border:1px solid rgba(255,170,0,.3)}
.endpoint-name{font-size:13px;font-weight:700;color:#fff;font-family:"Inter",sans-serif}
.endpoint-desc{font-size:11px;color:var(--sub);font-family:"Inter",sans-serif;margin-top:2px;flex:1 1 100%}
.url-box{display:flex;align-items:stretch;background:rgba(0,10,30,.5);border:1px solid var(--border);border-radius:6px;overflow:hidden;margin-top:6px}
.url-box code{flex:1;padding:9px 12px;font-size:11px;color:var(--light);overflow-x:auto;white-space:nowrap}
.url-box button{padding:0 14px;border:none;border-left:1px solid var(--border);background:rgba(0,30,80,.5);color:var(--sub);cursor:pointer;font-size:12px;font-family:inherit;font-weight:600}
.url-box button:hover{background:rgba(0,80,160,.6);color:#fff}
.params{font-size:11px;color:var(--muted);margin-top:6px;font-family:"Inter",sans-serif}
.params strong{color:var(--sub)}
.tester{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:720px){.tester{grid-template-columns:1fr}}
.tester-form{display:flex;flex-direction:column;gap:10px}
.tester label{font-size:11px;font-weight:600;color:var(--sub);text-transform:uppercase;letter-spacing:.4px}
.tester input,.tester select{background:rgba(0,20,50,.5);border:1px solid var(--border);color:#fff;padding:9px 12px;border-radius:7px;font-size:13px;font-family:inherit;outline:none}
.tester input:focus,.tester select:focus{border-color:var(--bright);box-shadow:0 0 0 3px rgba(0,150,255,.15)}
.tester button{background:linear-gradient(135deg,#0066ff,#0099ff);color:#fff;border:none;padding:10px;border-radius:7px;cursor:pointer;font-size:13px;font-weight:600;font-family:inherit}
.tester button:hover{filter:brightness(1.1)}
.tester button:disabled{opacity:.5;cursor:not-allowed}
.tester-output{background:var(--code);border:1px solid var(--border);border-radius:8px;padding:12px;min-height:200px;max-height:400px;overflow:auto;font-family:"JetBrains Mono",monospace;font-size:12px;color:var(--light);white-space:pre-wrap;word-break:break-word}
.tester-output.ok{border-color:rgba(0,230,118,.4)}
.tester-output.err{border-color:rgba(255,77,77,.4)}
.snippet-tabs{display:flex;gap:4px;margin-bottom:8px;flex-wrap:wrap}
.snippet-tab{padding:6px 12px;font-size:11px;font-weight:600;background:rgba(0,30,80,.4);border:1px solid var(--border);color:var(--sub);border-radius:6px;cursor:pointer}
.snippet-tab.active{background:rgba(0,100,200,.4);color:#fff;border-color:var(--bright)}
.snippet{background:var(--code);border:1px solid var(--border);border-radius:8px;padding:14px;font-family:"JetBrains Mono",monospace;font-size:11px;color:#a8d8ff;overflow-x:auto;white-space:pre;line-height:1.55;position:relative}
.snippet-copy{position:absolute;top:8px;right:8px;background:rgba(0,80,160,.5);border:1px solid var(--border);color:#fff;padding:4px 10px;border-radius:5px;cursor:pointer;font-size:10px;font-weight:600;font-family:inherit}
.snippet-copy:hover{background:rgba(0,150,255,.6)}
.toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--ok);color:#000;padding:10px 20px;border-radius:8px;font-size:13px;font-weight:600;opacity:0;transition:opacity .3s;pointer-events:none;z-index:9999}
.toast.show{opacity:1}
.tag{display:inline-block;font-size:10px;font-weight:600;padding:2px 7px;border-radius:4px;background:rgba(0,150,255,.15);color:var(--light);border:1px solid var(--border);margin-right:4px}
.tag-quick{background:rgba(168,85,247,.15);color:#c084fc;border-color:rgba(168,85,247,.3);cursor:pointer;font-family:"JetBrains Mono",monospace}
.tag-quick:hover{background:rgba(168,85,247,.3);color:#fff}
.row-flex{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.kbd{font-family:"JetBrains Mono",monospace;background:rgba(0,30,80,.5);padding:1px 6px;border-radius:3px;font-size:10px;color:var(--light)}
</style>
</head>
<body>
<div class="wrap">
  <div class="hdr">
    <div class="logo">TX</div>
    <div class="hdr-text">
      <h1>🌐 API Integration Dashboard</h1>
      <p>Endpoint URL, live tester, dan code snippet untuk integrasi external tools</p>
    </div>
  </div>

  <div class="tabs">
    <button class="tab active" onclick="switchTab(this, 'tab-endpoints')">📡 Endpoints</button>
    <button class="tab" onclick="switchTab(this, 'tab-tester')">⚡ Live Tester</button>
    <button class="tab" onclick="switchTab(this, 'tab-snippets')">💻 Code Snippets</button>
    <button class="tab" onclick="switchTab(this, 'tab-packages')">📦 Package Reference</button>
  </div>

  <!-- ===== TAB: ENDPOINTS ===== -->
  <div class="tab-content active" id="tab-endpoints">
    <div class="card">
      <div class="ct">📡 Available API Endpoints</div>
      <p style="font-size:12px;color:var(--sub);margin-bottom:14px;">
        Klik 📋 untuk salin URL ke clipboard. Ganti <span class="kbd">{CODE}</span> dengan voucher user, dan <span class="kbd">{FEATURE}</span> dengan ID aplikasi (mis. <span class="kbd">google-flow</span>).
      </p>

      <!-- check_member -->
      <div class="endpoint">
        <div class="endpoint-head">
          <span class="method GET">GET</span>
          <span class="endpoint-name">check_member</span>
          <span class="tag">PUBLIC</span>
        </div>
        <div class="endpoint-desc">Cek validitas voucher, paket, expiry date, dan fitur yang diizinkan.</div>
        <div class="url-box">
          <code id="url-1"><?php echo htmlspecialchars($base_url); ?>?action=check_member&code={CODE}</code>
          <button onclick="copyText(document.getElementById('url-1').textContent)">📋 Copy</button>
        </div>
        <div class="params"><strong>Params:</strong> <span class="kbd">code</span> (required) — voucher user</div>
      </div>

      <!-- feature_check -->
      <div class="endpoint">
        <div class="endpoint-head">
          <span class="method GET">GET</span>
          <span class="endpoint-name">feature_check</span>
          <span class="tag">PUBLIC</span>
        </div>
        <div class="endpoint-desc">Cek apakah voucher punya akses ke fitur/aplikasi tertentu.</div>
        <div class="url-box">
          <code id="url-2"><?php echo htmlspecialchars($base_url); ?>?action=feature_check&code={CODE}&feature={FEATURE}</code>
          <button onclick="copyText(document.getElementById('url-2').textContent)">📋 Copy</button>
        </div>
        <div class="params"><strong>Params:</strong> <span class="kbd">code</span>, <span class="kbd">feature</span> (e.g. google-flow, grok, single-sora)</div>
        <div class="row-flex">
          <strong style="font-size:11px;color:var(--sub);align-self:center">Fitur tersedia:</strong>
          <?php foreach ($activeApps as $a): ?>
            <span class="tag tag-quick" onclick="navigator.clipboard.writeText('<?php echo htmlspecialchars($a['id']); ?>');showToast('✓ '+'<?php echo htmlspecialchars($a['id']); ?>')"><?php echo htmlspecialchars($a['id']); ?></span>
          <?php endforeach; ?>
        </div>
      </div>

      <!-- get_user_projects -->
      <div class="endpoint">
        <div class="endpoint-head">
          <span class="method GET">GET</span>
          <span class="endpoint-name">get_user_projects</span>
          <span class="tag">PUBLIC</span>
        </div>
        <div class="endpoint-desc">Ambil daftar project Google Flow yang sudah disimpan user.</div>
        <div class="url-box">
          <code id="url-3"><?php echo htmlspecialchars($base_url); ?>?action=get_user_projects&code={CODE}</code>
          <button onclick="copyText(document.getElementById('url-3').textContent)">📋 Copy</button>
        </div>
        <div class="params"><strong>Params:</strong> <span class="kbd">code</span> (required)</div>
      </div>

      <!-- save_user_project -->
      <div class="endpoint">
        <div class="endpoint-head">
          <span class="method GET">GET</span>
          <span class="endpoint-name">save_user_project</span>
          <span class="tag">PUBLIC</span>
        </div>
        <div class="endpoint-desc">Simpan project URL ke voucher (max 10 project, FIFO rotation).</div>
        <div class="url-box">
          <code id="url-4"><?php echo htmlspecialchars($base_url); ?>?action=save_user_project&code={CODE}&project_url={URL}&server_name={SERVER}&payload_index={INDEX}</code>
          <button onclick="copyText(document.getElementById('url-4').textContent)">📋 Copy</button>
        </div>
        <div class="params"><strong>Params:</strong> <span class="kbd">code</span>, <span class="kbd">project_url</span>, <span class="kbd">server_name</span> (opt), <span class="kbd">payload_index</span> (opt)</div>
      </div>

      <!-- delete_user_project -->
      <div class="endpoint">
        <div class="endpoint-head">
          <span class="method GET">GET</span>
          <span class="endpoint-name">delete_user_project</span>
          <span class="tag">PUBLIC</span>
        </div>
        <div class="endpoint-desc">Hapus 1 project dari daftar user.</div>
        <div class="url-box">
          <code id="url-5"><?php echo htmlspecialchars($base_url); ?>?action=delete_user_project&code={CODE}&project_url={URL}</code>
          <button onclick="copyText(document.getElementById('url-5').textContent)">📋 Copy</button>
        </div>
      </div>
    </div>

    <?php if (!empty($sampleMembers)): ?>
    <div class="card">
      <div class="ct">⚡ Quick Test dengan Voucher Aktif</div>
      <p style="font-size:12px;color:var(--sub);margin-bottom:10px;">Klik untuk langsung test endpoint <span class="kbd">check_member</span> dengan voucher contoh:</p>
      <div class="row-flex">
        <?php foreach ($sampleMembers as $m): ?>
          <a class="tag tag-quick" target="_blank" href="<?php echo htmlspecialchars($base_url . '?action=check_member&code=' . urlencode($m['code'])); ?>"><?php echo htmlspecialchars($m['code']); ?></a>
        <?php endforeach; ?>
      </div>
    </div>
    <?php endif; ?>
  </div>

  <!-- ===== TAB: LIVE TESTER ===== -->
  <div class="tab-content" id="tab-tester">
    <div class="card">
      <div class="ct">⚡ Live API Tester</div>
      <div class="tester">
        <div class="tester-form">
          <label>Endpoint</label>
          <select id="t-action">
            <option value="check_member">check_member</option>
            <option value="feature_check">feature_check</option>
            <option value="get_user_projects">get_user_projects</option>
            <option value="save_user_project">save_user_project</option>
            <option value="delete_user_project">delete_user_project</option>
          </select>

          <label>Code (Voucher)</label>
          <input type="text" id="t-code" placeholder="mis. asudog123" value="<?php echo $sampleMembers ? htmlspecialchars($sampleMembers[0]['code']) : ''; ?>"/>

          <label id="lbl-feature">Feature ID</label>
          <select id="t-feature">
            <option value="">-- pilih fitur --</option>
            <?php foreach ($activeApps as $a): ?>
              <option value="<?php echo htmlspecialchars($a['id']); ?>"><?php echo htmlspecialchars($a['name']) . ' (' . htmlspecialchars($a['id']) . ')'; ?></option>
            <?php endforeach; ?>
          </select>

          <label id="lbl-url">Project URL</label>
          <input type="text" id="t-url" placeholder="/fx/tools/flow/project/abc-..." />

          <button id="t-submit" onclick="runTest()">🚀 Run Request</button>

          <label>Generated URL</label>
          <div class="url-box">
            <code id="t-genurl">—</code>
            <button onclick="copyText(document.getElementById('t-genurl').textContent)">📋</button>
          </div>
        </div>

        <div>
          <label style="font-size:11px;font-weight:600;color:var(--sub);text-transform:uppercase;letter-spacing:.4px;display:block;margin-bottom:8px">Response</label>
          <div id="t-output" class="tester-output">// Klik "Run Request" untuk melihat respons API</div>
          <div style="font-size:11px;color:var(--muted);margin-top:8px">
            ⏱ <span id="t-time">—</span> · 📦 <span id="t-size">—</span> · 🔢 <span id="t-status">—</span>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- ===== TAB: SNIPPETS ===== -->
  <div class="tab-content" id="tab-snippets">
    <div class="card">
      <div class="ct">💻 Code Snippets siap pakai</div>
      <div class="snippet-tabs">
        <button class="snippet-tab active" onclick="showSnippet(this,'snip-js')">JavaScript</button>
        <button class="snippet-tab" onclick="showSnippet(this,'snip-py')">Python</button>
        <button class="snippet-tab" onclick="showSnippet(this,'snip-php')">PHP</button>
        <button class="snippet-tab" onclick="showSnippet(this,'snip-curl')">cURL</button>
      </div>

      <div class="snippet" id="snip-js">
<button class="snippet-copy" onclick="copyText(document.getElementById('snip-js').dataset.raw)">📋 Copy</button><?php
$jsCode = <<<JS
const TEXA_API = '$base_url';

async function checkMember(code) {
  try {
    const res = await fetch(`\${TEXA_API}?action=check_member&code=\${encodeURIComponent(code)}`);
    return await res.json();
  } catch (e) {
    return { valid: false, reason: 'network_error', message: e.message };
  }
}

async function checkFeature(code, feature) {
  const url = `\${TEXA_API}?action=feature_check&code=\${encodeURIComponent(code)}&feature=\${encodeURIComponent(feature)}`;
  return await (await fetch(url)).json();
}

// Usage
const m = await checkMember('asudog123');
if (!m.valid) { alert('❌ ' + m.message); return; }

console.log(`✅ \${m.name} | Paket: \${m.package} | Sisa: \${m.days_remaining} hari`);

// Gating per fitur
if (m.allowed_features['bulk-sora']) {
  enableBulkSora();
} else {
  showUpgradePopup('Upgrade ke Ultimate untuk akses Bulk Sora');
}
JS;
echo htmlspecialchars($jsCode);
?></div>

      <div class="snippet" id="snip-py" style="display:none">
<button class="snippet-copy" onclick="copyText(document.getElementById('snip-py').dataset.raw)">📋 Copy</button><?php
$pyCode = <<<PY
import requests

TEXA_API = '$base_url'

def check_member(code: str) -> dict:
    try:
        r = requests.get(TEXA_API, params={'action': 'check_member', 'code': code}, timeout=10)
        return r.json()
    except Exception as e:
        return {'valid': False, 'reason': 'network_error', 'message': str(e)}

def check_feature(code: str, feature: str) -> dict:
    r = requests.get(TEXA_API, params={
        'action': 'feature_check', 'code': code, 'feature': feature
    }, timeout=10)
    return r.json()

# Usage
m = check_member('asudog123')
if not m.get('valid'):
    print(f"❌ {m.get('message')}")
    exit(1)

print(f"✅ {m['name']} | Paket: {m['package'].upper()} | Sisa: {m['days_remaining']} hari")

# Cek fitur
if 'bulk-sora' in m.get('allowed_features', {}):
    print('🚀 Bulk Sora unlocked')
else:
    print('🔒 Bulk Sora: Upgrade ke Ultimate')
PY;
echo htmlspecialchars($pyCode);
?></div>

      <div class="snippet" id="snip-php" style="display:none">
<button class="snippet-copy" onclick="copyText(document.getElementById('snip-php').dataset.raw)">📋 Copy</button><?php
$phpCode = <<<PHP
<?php
function texaCheckMember(string \$code): array {
    \$url = '$base_url?action=check_member&code=' . urlencode(\$code);
    \$ctx = stream_context_create(['http' => ['timeout' => 10]]);
    \$raw = @file_get_contents(\$url, false, \$ctx);
    if (\$raw === false) return ['valid' => false, 'reason' => 'network_error'];
    return json_decode(\$raw, true) ?: ['valid' => false, 'reason' => 'parse_error'];
}

function texaCheckFeature(string \$code, string \$feature): array {
    \$url = '$base_url?action=feature_check&code=' . urlencode(\$code)
         . '&feature=' . urlencode(\$feature);
    \$raw = @file_get_contents(\$url);
    return json_decode(\$raw, true) ?: ['valid' => false];
}

// Usage
\$m = texaCheckMember('asudog123');
if (!\$m['valid']) {
    http_response_code(403);
    exit('Akses ditolak: ' . (\$m['message'] ?? ''));
}

\$pkg = \$m['package'];
echo "Welcome " . htmlspecialchars(\$m['name']) . " — Paket: " . strtoupper(\$pkg);

// Gating
\$maxRequest = match(\$pkg) {
    'basic'    => 50,
    'pro'      => 200,
    'ultimate' => 1000,
    default    => 10,
};
PHP;
echo htmlspecialchars($phpCode);
?></div>

      <div class="snippet" id="snip-curl" style="display:none">
<button class="snippet-copy" onclick="copyText(document.getElementById('snip-curl').dataset.raw)">📋 Copy</button><?php
$curlCode = <<<CURL
# Check member
curl "$base_url?action=check_member&code=asudog123"

# Feature check
curl "$base_url?action=feature_check&code=asudog123&feature=google-flow"

# Get user projects
curl "$base_url?action=get_user_projects&code=asudog123"
CURL;
echo htmlspecialchars($curlCode);
?></div>
    </div>
  </div>

  <!-- ===== TAB: PACKAGES ===== -->
  <div class="tab-content" id="tab-packages">
    <div class="card">
      <div class="ct">📦 Reference Mapping Paket → Fitur</div>
      <p style="font-size:12px;color:var(--sub);margin-bottom:14px">
        Default mapping (kecuali ada <span class="kbd">custom_config</span> per voucher di <a href="dashboard.php" style="color:var(--light)">admin dashboard</a>):
      </p>

      <?php
      $packages = loadData('packages.json');
      $mainPkg = $packages['main'] ?? [];
      if (isset($mainPkg['basic']) && !is_array($mainPkg['basic'])) {
          $mainPkg = [
              'basic'    => ['google-flow'=>3, 'google-whisk'=>3, 'single-sora'=>1],
              'pro'      => ['google-flow'=>3, 'google-whisk'=>3, 'grok'=>3, 'single-sora'=>1],
              'ultimate' => ['google-flow'=>5, 'google-whisk'=>5, 'grok'=>5, 'single-sora'=>1, 'bulk-sora'=>1],
              'trial'    => ['google-flow'=>1],
          ];
      }
      $colorMap = [
          'basic' => '#4db8ff', 'pro' => '#a855f7',
          'ultimate' => '#ffaa00', 'trial' => '#00e676', 'custom' => '#ff8080'
      ];
      foreach (['basic','pro','ultimate','trial'] as $pkgName):
          if (!isset($mainPkg[$pkgName])) continue;
          $pkgFeatures = $mainPkg[$pkgName];
          $color = $colorMap[$pkgName] ?? '#fff';
      ?>
      <div style="background:rgba(0,30,80,.3);border:1px solid var(--border);border-radius:10px;padding:14px;margin-bottom:10px">
        <div style="display:flex;align-items:center;gap:10px;margin-bottom:10px">
          <span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:<?php echo $color; ?>"></span>
          <span style="font-size:14px;font-weight:700;color:#fff;text-transform:uppercase;letter-spacing:.5px"><?php echo $pkgName; ?></span>
        </div>
        <div class="row-flex">
          <?php foreach ($pkgFeatures as $feat => $maxSrv): ?>
            <span class="tag" style="background:rgba(0,150,255,.1)"><?php echo htmlspecialchars($feat); ?> <span style="opacity:.7">×<?php echo (int)$maxSrv; ?></span></span>
          <?php endforeach; ?>
        </div>
      </div>
      <?php endforeach; ?>

      <div style="background:rgba(168,85,247,.08);border:1px solid rgba(168,85,247,.2);border-radius:10px;padding:14px;margin-top:14px;font-size:12px;color:var(--sub);line-height:1.6">
        <strong style="color:#c084fc">💡 Tip:</strong> Gunakan field <span class="kbd">allowed_features</span> di response API untuk gating, karena ini sudah memperhitungkan <span class="kbd">custom_config</span> per voucher (jika di-override admin).
      </div>
    </div>
  </div>

  <p style="text-align:center;font-size:10px;color:var(--muted);opacity:.5;margin-top:30px">TEKNO-APPS API Dashboard &copy; 2026</p>
</div>

<div id="toast" class="toast"></div>

<script>
const BASE_URL = <?php echo json_encode($base_url); ?>;

function switchTab(btn, id) {
    document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
    document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
    btn.classList.add('active');
    document.getElementById(id).classList.add('active');
}

function showSnippet(btn, id) {
    document.querySelectorAll('.snippet-tab').forEach(t => t.classList.remove('active'));
    document.querySelectorAll('.snippet').forEach(s => s.style.display = 'none');
    btn.classList.add('active');
    document.getElementById(id).style.display = 'block';
}

function copyText(text) {
    const fallback = () => {
        const ta = document.createElement('textarea');
        ta.value = text; ta.style.position='fixed'; ta.style.opacity='0';
        document.body.appendChild(ta); ta.select();
        try { document.execCommand('copy'); } catch(e) {}
        document.body.removeChild(ta);
    };
    if (navigator.clipboard?.writeText) {
        navigator.clipboard.writeText(text).catch(fallback);
    } else fallback();
    showToast('✓ Disalin ke clipboard');
}

function showToast(msg) {
    const t = document.getElementById('toast');
    t.textContent = msg;
    t.classList.add('show');
    setTimeout(() => t.classList.remove('show'), 1600);
}

// Save raw snippet content (without HTML escaping) for copying
document.querySelectorAll('.snippet').forEach(s => {
    const cloned = s.cloneNode(true);
    cloned.querySelectorAll('button').forEach(b => b.remove());
    s.dataset.raw = cloned.textContent.trim();
});

// Live tester
const tAction = document.getElementById('t-action');
const tCode = document.getElementById('t-code');
const tFeature = document.getElementById('t-feature');
const tUrl = document.getElementById('t-url');
const tGenUrl = document.getElementById('t-genurl');

function buildUrl() {
    const action = tAction.value;
    const code = encodeURIComponent(tCode.value.trim());
    let url = `${BASE_URL}?action=${action}&code=${code}`;
    if (action === 'feature_check' && tFeature.value) {
        url += '&feature=' + encodeURIComponent(tFeature.value);
    }
    if ((action === 'save_user_project' || action === 'delete_user_project') && tUrl.value) {
        url += '&project_url=' + encodeURIComponent(tUrl.value);
    }
    tGenUrl.textContent = url;
    return url;
}

function updateTesterFields() {
    const action = tAction.value;
    document.getElementById('lbl-feature').style.display = action === 'feature_check' ? 'block' : 'none';
    tFeature.style.display = action === 'feature_check' ? 'block' : 'none';
    const showUrl = (action === 'save_user_project' || action === 'delete_user_project');
    document.getElementById('lbl-url').style.display = showUrl ? 'block' : 'none';
    tUrl.style.display = showUrl ? 'block' : 'none';
    buildUrl();
}

tAction.addEventListener('change', updateTesterFields);
[tCode, tFeature, tUrl].forEach(el => el.addEventListener('input', buildUrl));
updateTesterFields();

async function runTest() {
    const btn = document.getElementById('t-submit');
    const out = document.getElementById('t-output');
    const url = buildUrl();
    btn.disabled = true;
    btn.textContent = '⏳ Loading...';
    out.classList.remove('ok', 'err');
    out.textContent = '// Loading...';
    const t0 = performance.now();
    try {
        const res = await fetch(url);
        const text = await res.text();
        const dt = (performance.now() - t0).toFixed(0);
        let pretty = text;
        try { pretty = JSON.stringify(JSON.parse(text), null, 2); } catch(e) {}
        out.textContent = pretty;
        out.classList.add(res.ok ? 'ok' : 'err');
        document.getElementById('t-time').textContent = dt + ' ms';
        document.getElementById('t-size').textContent = (text.length / 1024).toFixed(2) + ' KB';
        document.getElementById('t-status').textContent = res.status + ' ' + res.statusText;
    } catch (e) {
        out.textContent = 'Network Error:\n' + e.message;
        out.classList.add('err');
    } finally {
        btn.disabled = false;
        btn.textContent = '🚀 Run Request';
    }
}
</script>
</body>
</html>
