<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>UI Components - Admin</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
  </head>
  <body class="bg-gray-100">
    <div id="app" class="min-h-screen">
      <div class="bg-white shadow">
        <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
          <div class="flex justify-between items-center">
            <div>
              <h1 class="text-2xl font-bold text-gray-900">UI Components</h1>
              <p class="text-sm text-gray-600 mt-1">Manage projects, UI components, and assignments.</p>
            </div>
          </div>
        </div>
      </div>

      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-8">
        <div v-if="toast.show" class="fixed top-4 right-4 z-50">
          <div :class="['px-4 py-3 rounded shadow text-sm', toast.type === 'error' ? 'bg-red-600 text-white' : 'bg-green-600 text-white']">
            {{ toast.message }}
          </div>
        </div>

        <div class="bg-white rounded-lg shadow p-4">
          <div class="flex items-center justify-between">
            <div>
              <h2 class="font-semibold text-gray-800">Using the system endpoints & SDK</h2>
              <p class="text-xs text-gray-500">Quick reference for public endpoints and the browser SDK.</p>
            </div>
            <button
              @click="toggleHelp"
              class="text-xs px-2 py-1 rounded border border-gray-200 bg-gray-50 hover:bg-gray-100 text-gray-700"
            >
              {{ helpOpen ? 'Hide' : 'Show' }}
            </button>
          </div>

          <div v-if="helpOpen" class="mt-3 space-y-4 text-sm text-gray-700">
            <div>
              <h3 class="font-semibold text-gray-800 mb-1">Public API endpoints</h3>
              <p class="text-xs text-gray-500 mb-2">All paths are relative to this backend base URL.</p>
              <pre class="text-[11px] bg-gray-50 border border-gray-200 rounded p-2 whitespace-pre-wrap break-words"><code>
GET {{ baseUrl }}/api/ui-components/manifest/:projectId
GET {{ baseUrl }}/api/ui-components/component/:code

// Private projects require an API key header
//   x-project-key: YOUR_PROJECT_API_KEY

curl "{{ baseUrl }}/api/ui-components/manifest/prj_yourproject" \
  -H "x-project-key: YOUR_PROJECT_API_KEY"
              </code></pre>
            </div>

            <div>
              <h3 class="font-semibold text-gray-800 mb-1">Browser SDK</h3>
              <p class="text-xs text-gray-500 mb-2">Include the SDK bundle and initialize it with your project.</p>
              <pre class="text-[11px] bg-gray-50 border border-gray-200 rounded p-2 whitespace-pre-wrap break-words"><code>
&lt;script src="{{ baseUrl }}/public/sdk/ui-components.iife.js"&gt;&lt;/script&gt;
&lt;script&gt;
  uiCmp.init({
    projectId: 'prj_yourproject',
    apiKey: 'YOUR_PROJECT_API_KEY', // null for public projects
    apiUrl: '{{ baseUrl }}',
  });

  // Alias also available
  // uiComponents.init(...same config...);
&lt;/script&gt;
              </code></pre>
            </div>

            <div>
              <h3 class="font-semibold text-gray-800 mb-1">Auto-inject snippet (single script tag)</h3>
              <p class="text-xs text-gray-500 mb-2">Paste this anywhere; it uses the SDK host’s origin and avoids duplicate injection.</p>
              <pre class="autoInjectSnippet text-[11px] bg-gray-50 border border-gray-200 rounded p-2 whitespace-pre-wrap break-words"><code>
&lt;script&gt;
(function () {
  // ---- CONFIG ----
  const SCRIPT_SRC = '__ORIGIN__{{ baseUrl }}/public/sdk/ui-components.iife.js';
  const INIT_OPTS = {
    projectId: 'prj_yourproject',
    apiKey: null, // set string for private projects
    apiUrl: '{{ baseUrl }}',
  };

  // ---- GUARDS (idempotent) ----
  if (window.__uiCmpAutoAdded) return;
  window.__uiCmpAutoAdded = true;

  function initUiCmp() {
    if (!window.uiCmp || window.__uiCmpInitialized) return;
    window.__uiCmpInitialized = true;
    window.uiCmp.init(INIT_OPTS);
  }

  // ---- SCRIPT LOADER ----
  if (window.uiCmp) {
    // SDK already loaded
    initUiCmp();
    return;
  }

  // Avoid duplicate &lt;script&gt; injection
  const existing = document.querySelector('script[src="' + SCRIPT_SRC + '"]');
  if (existing) {
    existing.addEventListener('load', initUiCmp, { once: true });
    return;
  }

  const s = document.createElement('script');
  s.src = SCRIPT_SRC;
  s.async = true;
  s.onload = initUiCmp;
  document.head.appendChild(s);
})();
&lt;/script&gt;
              </code></pre>
            </div>

            <div>
              <h3 class="font-semibold text-gray-800 mb-1">Project setup checklist</h3>
              <ul class="list-disc pl-5 space-y-1 text-xs text-gray-700">
                <li>Create a project (public or private) in the Projects panel.</li>
                <li>Create one or more components and assign them to the project.</li>
                <li v-if="selectedProject && !selectedProject.isPublic">For private projects, copy the API key when it is shown (once) after creation or rotation.</li>
                <li>Optionally configure allowed origins on the project.</li>
                <li>Use the manifest endpoint or SDK to render components on your site.</li>
              </ul>
            </div>

            <div>
              <h3 class="font-semibold text-gray-800 mb-1">Troubleshooting</h3>
              <ul class="list-disc pl-5 space-y-1 text-xs text-gray-700">
                <li>401/403 on private projects usually means a missing or invalid <code>x-project-key</code>.</li>
                <li>Check that the project is active and the component is assigned and enabled.</li>
                <li>Verify that the SDK script URL matches this admin base URL ({{ baseUrl }}).</li>
              </ul>
            </div>
          </div>
        </div>

        <!-- Import / Export & Gallery toggle (C2, C4) -->
        <div class="bg-white rounded-lg shadow p-4">
          <div class="flex items-center justify-between flex-wrap gap-3">
            <div class="flex items-center gap-2">
              <button @click="activeTab = 'manage'" :class="['text-sm px-3 py-1.5 rounded', activeTab === 'manage' ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200']">
                Manage
              </button>
              <button @click="activeTab = 'gallery'; loadGalleryComponents()" :class="['text-sm px-3 py-1.5 rounded', activeTab === 'gallery' ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200']">
                Gallery
              </button>
            </div>
            <div class="flex items-center gap-2">
              <button @click="exportComponents" class="text-xs px-3 py-1.5 rounded bg-gray-700 hover:bg-gray-800 text-white">Export JSON</button>
              <label class="text-xs px-3 py-1.5 rounded bg-gray-700 hover:bg-gray-800 text-white cursor-pointer">
                Import JSON
                <input type="file" accept=".json" class="hidden" @change="importComponents" />
              </label>
            </div>
          </div>
        </div>

        <!-- Gallery tab (C4) -->
        <div v-if="activeTab === 'gallery'" class="bg-white rounded-lg shadow p-4 space-y-4">
          <h2 class="font-semibold text-gray-800">Component Gallery</h2>
          <p class="text-xs text-gray-500">Visual preview of all components using their <code>previewExample</code> HTML or default HTML.</p>
          <div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
            <div v-for="c in galleryComponents" :key="c.code" class="border border-gray-200 rounded-lg overflow-hidden">
              <div class="bg-gray-50 border-b border-gray-200 px-3 py-2 flex items-center justify-between">
                <div>
                  <div class="font-medium text-sm text-gray-900">{{ c.name }}</div>
                  <div class="text-xs text-gray-500">{{ c.code }} · v{{ c.version || 1 }}</div>
                </div>
                <button @click="loadComponentIntoEditor(c.code); activeTab = 'manage'" class="text-xs px-2 py-1 rounded bg-blue-100 hover:bg-blue-200 text-blue-700">Edit</button>
              </div>
              <div class="h-48 bg-white">
                <iframe :srcdoc="buildGalleryPreviewHtml(c)" class="w-full h-full border-0" sandbox="allow-scripts"></iframe>
              </div>
            </div>
          </div>
          <div v-if="galleryComponents.length === 0" class="text-sm text-gray-500 p-4 text-center bg-gray-50 rounded">No components found.</div>
        </div>

        <!-- Version history panel (C1) -->
        <div v-if="versionHistory.length > 0" class="bg-white rounded-lg shadow p-4 space-y-3">
          <div class="flex items-center justify-between">
            <h2 class="font-semibold text-gray-800">Version History — {{ componentEditor.code }}</h2>
            <button @click="versionHistory = []" class="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200">Close</button>
          </div>
          <div class="max-h-60 overflow-auto space-y-1">
            <div v-for="v in versionHistory" :key="v._id" class="flex items-center justify-between text-sm border border-gray-200 rounded px-3 py-2 bg-gray-50">
              <div>
                <span class="font-mono text-xs text-gray-700">v{{ v.version }}</span>
                <span class="text-xs text-gray-500 ml-2">{{ new Date(v.savedAt).toLocaleString() }}</span>
              </div>
              <button @click="restoreVersion(v._id)" class="text-xs px-2 py-1 rounded bg-amber-100 hover:bg-amber-200 text-amber-700">Restore</button>
            </div>
          </div>
        </div>

        <div v-show="activeTab === 'manage'" class="grid grid-cols-1 lg:grid-cols-3 gap-6">
          <div class="bg-white rounded-lg shadow p-4 space-y-4">
            <div class="flex items-center justify-between">
              <h2 class="font-semibold text-gray-800">Projects</h2>
              <button @click="refreshAll" class="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200">Refresh</button>
            </div>

            <div class="space-y-2">
              <input v-model="newProject.name" class="w-full border rounded px-3 py-2 text-sm" placeholder="Project name" />
              <input v-model="newProject.projectId" class="w-full border rounded px-3 py-2 text-sm" placeholder="projectId (optional, prj_...)" />
              <label class="flex items-center gap-2 text-sm">
                <input type="checkbox" v-model="newProject.isPublic" />
                Public
              </label>
              <button @click="createProject" class="w-full bg-blue-600 hover:bg-blue-700 text-white text-sm px-3 py-2 rounded">Create project</button>
            </div>

            <div class="border-t pt-3">
              <div class="text-xs text-gray-500 mb-2">Select a project:</div>
              <div class="space-y-1 max-h-[420px] overflow-auto">
                <button
                  v-for="p in projects"
                  :key="p.projectId"
                  @click="selectProject(p)"
                  :class="['w-full text-left px-3 py-2 rounded text-sm border', selectedProject && selectedProject.projectId === p.projectId ? 'bg-blue-50 border-blue-300' : 'bg-white border-gray-200 hover:bg-gray-50']"
                >
                  <div class="font-medium text-gray-900">{{ p.name }}</div>
                  <div class="text-xs text-gray-500">{{ p.projectId }} · <span :class="p.isPublic ? 'text-green-600' : 'text-amber-600'">{{ p.isPublic ? 'public' : 'private' }}</span></div>
                </button>
              </div>
            </div>
          </div>

          <div class="bg-white rounded-lg shadow p-4 space-y-4">
            <div class="flex items-center justify-between">
              <h2 class="font-semibold text-gray-800">Components</h2>
            </div>

            <div class="space-y-2">
              <input v-model="componentEditor.code" class="w-full border rounded px-3 py-2 text-sm" placeholder="code (e.g. toast)" />
              <input v-model="componentEditor.name" class="w-full border rounded px-3 py-2 text-sm" placeholder="name" />
              <textarea v-model="componentEditor.html" class="w-full border rounded px-3 py-2 text-sm font-mono" rows="4" placeholder="html"></textarea>
              <textarea v-model="componentEditor.css" class="w-full border rounded px-3 py-2 text-sm font-mono" rows="3" placeholder="css"></textarea>
              <textarea v-model="componentEditor.js" class="w-full border rounded px-3 py-2 text-sm font-mono" rows="6" placeholder="js (return { show(){...} })"></textarea>
              <textarea v-model="componentEditor.usageMarkdown" class="w-full border rounded px-3 py-2 text-sm" rows="3" placeholder="usageMarkdown"></textarea>

              <div class="flex gap-2">
                <button @click="saveComponent" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white text-sm px-3 py-2 rounded">Save</button>
                <button @click="clearComponentEditor" class="px-3 py-2 rounded text-sm bg-gray-100 hover:bg-gray-200">Clear</button>
              </div>
            </div>

            <div class="border-t pt-3 space-y-3">
              <div class="flex items-center justify-between">
                <div>
                  <div class="font-semibold text-gray-900">AI Assist</div>
                  <div class="text-xs text-gray-500">Propose edits and apply into editor (manual Save).</div>
                </div>
                <button @click="loadLlmConfig" class="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200">Reload LLM</button>
              </div>

              <div class="grid grid-cols-1 md:grid-cols-2 gap-2">
                <%- include('partials/llm-provider-model-picker', {
                  providerInputId: 'uiComponentsAiProviderKey',
                  modelInputId: 'uiComponentsAiModel',
                  providerLabel: 'Provider',
                  modelLabel: 'Model',
                  showOpenRouterFetch: true,
                }) %>
              </div>

              <div>
                <label class="block text-xs font-medium text-gray-600 mb-1">Prompt</label>
                <textarea v-model="ai.prompt" class="w-full border rounded px-2 py-2 text-sm" rows="3" placeholder="Describe the change you want..."></textarea>
              </div>

              <div class="grid grid-cols-1 md:grid-cols-2 gap-2">
                <div>
                  <label class="block text-xs font-medium text-gray-600 mb-1">Targets</label>
                  <div class="flex flex-wrap gap-3 text-xs text-gray-700">
                    <label class="flex items-center gap-1"><input type="checkbox" v-model="ai.targets.html" /> html</label>
                    <label class="flex items-center gap-1"><input type="checkbox" v-model="ai.targets.css" /> css</label>
                    <label class="flex items-center gap-1"><input type="checkbox" v-model="ai.targets.js" /> js</label>
                    <label class="flex items-center gap-1"><input type="checkbox" v-model="ai.targets.usageMarkdown" /> usage</label>
                  </div>
                </div>
                <div>
                  <label class="block text-xs font-medium text-gray-600 mb-1">Mode</label>
                  <select v-model="ai.mode" class="w-full border rounded px-2 py-2 text-sm">
                    <option value="minimal">minimal</option>
                    <option value="rewrite">rewrite</option>
                  </select>
                </div>
              </div>

              <div class="flex gap-2">
                <button @click="aiPropose" class="flex-1 px-3 py-2 rounded text-sm bg-purple-600 hover:bg-purple-700 text-white" :disabled="aiLoading">
                  {{ aiLoading ? 'Proposing...' : 'Propose' }}
                </button>
                <button @click="aiApply" class="px-3 py-2 rounded text-sm bg-gray-800 hover:bg-gray-900 text-white" :disabled="!aiProposal">
                  Apply
                </button>
              </div>

              <div v-if="aiWarnings.length" class="text-xs bg-amber-50 border border-amber-200 rounded p-2">
                <div class="font-semibold text-amber-900 mb-1">Warnings</div>
                <ul class="list-disc pl-5 space-y-1">
                  <li v-for="(w, idx) in aiWarnings" :key="idx" class="text-amber-900">{{ w }}</li>
                </ul>
              </div>

              <div v-if="aiProposal" class="text-xs bg-gray-50 border border-gray-200 rounded p-2">
                <div class="font-semibold text-gray-700 mb-1">Patch preview</div>
                <pre class="whitespace-pre-wrap break-words text-[11px]">{{ aiProposal.patch }}</pre>
              </div>
            </div>

                </div>
              </div>
            </div>

            <div class="border-t pt-3">
              <div class="flex items-center justify-between mb-2">
                <div class="text-xs text-gray-500">Existing components:</div>
                <button v-if="componentEditor.code" @click="loadVersionHistory(componentEditor.code)" class="text-[11px] px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 text-gray-700">History</button>
              </div>
              <div class="space-y-1 max-h-[320px] overflow-auto">
                <button
                  v-for="c in components"
                  :key="c.code"
                  @click="loadComponentIntoEditor(c.code)"
                  class="w-full text-left px-3 py-2 rounded text-sm border border-gray-200 hover:bg-gray-50"
                >
                  <div class="font-medium text-gray-900">{{ c.name }}</div>
                  <div class="text-xs text-gray-500">{{ c.code }} · v{{ c.version || 1 }}</div>
                </button>
              </div>
            </div>
          </div>

          <div class="bg-white rounded-lg shadow p-4 space-y-4">
            <div class="flex items-center justify-between">
              <h2 class="font-semibold text-gray-800">Assignments</h2>
            </div>

            <div v-if="!selectedProject" class="text-sm text-gray-500">
              Select a project to manage enabled components.
            </div>

            <div v-else class="space-y-3">
              <div class="text-sm">
                <div class="font-medium text-gray-900">{{ selectedProject.name }}</div>
                <div class="text-xs text-gray-500">{{ selectedProject.projectId }}</div>
              </div>

              <div class="space-y-2">
                <label class="flex items-center gap-2 text-sm">
                  <input type="checkbox" v-model="selectedProject.isPublic" @change="toggleProjectPublic" />
                  Public
                </label>

                <button v-if="!selectedProject.isPublic" @click="rotateKey" class="w-full text-sm px-3 py-2 rounded bg-amber-600 hover:bg-amber-700 text-white">
                  Rotate API Key
                </button>

                <div v-if="lastGeneratedKey" class="text-xs bg-gray-50 border border-gray-200 rounded p-2 break-all">
                  <div class="font-semibold text-gray-700 mb-1">API Key (shown once)</div>
                  <div class="font-mono">{{ lastGeneratedKey }}</div>
                </div>

                <div class="text-xs bg-gray-50 border border-gray-200 rounded p-2">
                  <div class="font-semibold text-gray-700 mb-1">Integration snippet</div>
                  <pre class="text-[11px] whitespace-pre-wrap">&lt;script src=&quot;{{ baseUrl }}/public/sdk/ui-components.iife.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
  uiCmp.init({ projectId: '{{ selectedProject.projectId }}', apiKey: {{ selectedProject.isPublic ? 'null' : "'YOUR_KEY'" }}, apiUrl: '{{ baseUrl }}' });
&lt;/script&gt;</pre>
                </div>
              </div>

              <div class="border-t pt-3">
                <div class="text-xs text-gray-500 mb-2">Enable components:</div>
                <div class="space-y-2 max-h-[360px] overflow-auto">
                  <label v-for="c in components" :key="c.code" class="flex items-center justify-between gap-3 text-sm border border-gray-200 rounded px-3 py-2">
                    <div>
                      <div class="font-medium text-gray-900">{{ c.name }}</div>
                      <div class="text-xs text-gray-500">{{ c.code }}</div>
                    </div>
                    <input type="checkbox" :checked="isAssigned(c.code)" @change="(e) => toggleAssignment(c.code, e.target.checked)" />
                  </label>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="bg-white rounded-lg shadow p-4 space-y-4" ref="previewContainerRef">
          <div class="flex flex-wrap items-center justify-between gap-2">
            <div>
              <h2 class="font-semibold text-gray-800">Preview & Test</h2>
              <p class="text-xs text-gray-500">Test current editor content without saving. Default mode: iframe.</p>
            </div>
            <div class="flex items-center gap-2">
              <button @click="runPreview" class="text-xs px-3 py-2 rounded bg-blue-600 hover:bg-blue-700 text-white">Run Preview</button>
              <button @click="resetPreview" class="text-xs px-3 py-2 rounded bg-gray-100 hover:bg-gray-200">Reset</button>
              <button @click="togglePreviewFullscreen" class="text-xs px-3 py-2 rounded bg-gray-800 hover:bg-gray-900 text-white">
                {{ previewFullscreen ? 'Exit Fullscreen (Esc)' : 'Fullscreen' }}
              </button>
            </div>
          </div>

          <div class="grid grid-cols-1 lg:grid-cols-4 gap-3">
            <div>
              <label class="block text-xs font-medium text-gray-600 mb-1">Mode</label>
              <select v-model="previewMode" class="w-full border rounded px-2 py-2 text-sm">
                <option value="iframe">iframe (dynamic)</option>
                <option value="top">top-frame (isolated)</option>
                <option value="top-no-isolation">top-frame (not isolated)</option>
              </select>
            </div>
            <div>
              <label class="block text-xs font-medium text-gray-600 mb-1">CSS Isolation</label>
              <select v-model="previewCssIsolation" class="w-full border rounded px-2 py-2 text-sm">
                <option value="scoped">scoped</option>
                <option value="shadow">shadow</option>
              </select>
            </div>
            <div class="lg:col-span-2">
              <label class="block text-xs font-medium text-gray-600 mb-1">Props JSON</label>
              <input v-model="previewPropsJson" class="w-full border rounded px-2 py-2 text-sm font-mono" placeholder='{"message":"Hello"}' />
            </div>
          </div>

          <div class="text-xs text-gray-500">
            Status: <span class="font-medium text-gray-700">{{ previewStatus }}</span>
            <span class="ml-2">Use the API runner below with flexible JS commands.</span>
          </div>

          <div class="border border-gray-200 rounded overflow-hidden">
            <div v-show="previewMode !== 'iframe'" class="h-[380px] bg-gray-50">
              <div ref="previewTopMountRef" class="h-full w-full"></div>
            </div>
            <div v-show="previewMode === 'iframe'" class="h-[380px] bg-gray-50">
              <iframe
                ref="previewIframeRef"
                title="UI Component Preview"
                class="w-full h-full border-0"
                sandbox="allow-scripts allow-same-origin"
              ></iframe>
            </div>
          </div>

          <div class="border border-gray-200 rounded p-3 space-y-2">
            <div class="flex items-center justify-between">
              <h3 class="font-semibold text-sm text-gray-800">JS API Runner</h3>
              <div class="flex gap-2">
                <button @click="setPreviewCommandExample('create')" class="text-[11px] px-2 py-1 rounded bg-gray-100 hover:bg-gray-200">Example: create</button>
                <button @click="setPreviewCommandExample('call')" class="text-[11px] px-2 py-1 rounded bg-gray-100 hover:bg-gray-200">Example: call method</button>
                <button @click="setPreviewCommandExample('destroy')" class="text-[11px] px-2 py-1 rounded bg-gray-100 hover:bg-gray-200">Example: destroy</button>
              </div>
            </div>
            <textarea v-model="previewCommand" rows="4" class="w-full border rounded px-2 py-2 text-xs font-mono" placeholder="await uiCmp.create({ message: 'Hi from preview' })"></textarea>
            <div class="flex gap-2">
              <button @click="runPreviewCommand" class="text-xs px-3 py-2 rounded bg-purple-600 hover:bg-purple-700 text-white">Run command</button>
              <button @click="clearPreviewLogs" class="text-xs px-3 py-2 rounded bg-gray-100 hover:bg-gray-200">Clear logs</button>
            </div>
            <pre class="text-[11px] bg-gray-50 border border-gray-200 rounded p-2 whitespace-pre-wrap break-words max-h-56 overflow-auto">{{ previewLogsText }}</pre>
          </div>
        </div>
      </div>
    </div>
    <script>
      window.__adminUiComponentsConfig = {
        baseUrl: '<%= baseUrl %>',
        adminPath: '<%= adminPath %>',
      };
    </script>
    <script src="<%= baseUrl %>/public/js/admin-ui-components-preview.js"></script>
    <script src="<%= baseUrl %>/public/js/llm-provider-model-picker.js"></script>
    <script src="<%= baseUrl %>/public/js/admin-ui-components.js"></script>
  </body>
</html>
