// Auto-generated: exports inspector.html content as a string for Cloudflare Workers
// Source of truth is inspector.html — keep in sync manually or via build step

export const inspectorHtml = `<!DOCTYPE html>
<html lang="zh-TW">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>u6u MCP Server 測試界面</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    :root {
      --bg: #0f1117;
      --surface: #1a1d27;
      --surface2: #22263a;
      --border: #2e3350;
      --accent: #6c8ef5;
      --accent-hover: #8aa4ff;
      --text: #e2e8f0;
      --text-muted: #8892a4;
      --error-bg: #3b1a1a;
      --error-border: #c0392b;
      --error-text: #ff6b6b;
      --success-bg: #1a2e1a;
      --success-border: #27ae60;
      --radius: 8px;
      --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      --mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
    }

    body {
      font-family: var(--font);
      background: var(--bg);
      color: var(--text);
      min-height: 100vh;
      display: flex;
      flex-direction: column;
    }

    header {
      background: var(--surface);
      border-bottom: 1px solid var(--border);
      padding: 16px 24px;
      display: flex;
      align-items: center;
      gap: 16px;
      flex-wrap: wrap;
    }

    .logo {
      font-size: 18px;
      font-weight: 700;
      color: var(--accent);
      letter-spacing: -0.5px;
    }

    .logo span { color: var(--text-muted); font-weight: 400; font-size: 14px; margin-left: 8px; }

    .api-key-group {
      display: flex;
      align-items: center;
      gap: 8px;
      margin-left: auto;
      flex-wrap: wrap;
    }

    .api-key-group label {
      font-size: 13px;
      color: var(--text-muted);
      white-space: nowrap;
    }

    .api-key-group input {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      color: var(--text);
      font-family: var(--mono);
      font-size: 13px;
      padding: 7px 12px;
      width: 280px;
      outline: none;
      transition: border-color 0.15s;
    }

    .api-key-group input:focus { border-color: var(--accent); }

    .key-status {
      width: 8px; height: 8px;
      border-radius: 50%;
      background: var(--border);
      flex-shrink: 0;
      transition: background 0.2s;
    }

    .key-status.active { background: #27ae60; }

    main {
      display: flex;
      flex: 1;
      overflow: hidden;
    }

    aside {
      width: 260px;
      min-width: 200px;
      background: var(--surface);
      border-right: 1px solid var(--border);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    .sidebar-header {
      padding: 14px 16px;
      font-size: 11px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.8px;
      color: var(--text-muted);
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .tool-count {
      background: var(--surface2);
      border-radius: 10px;
      padding: 2px 7px;
      font-size: 11px;
      color: var(--text-muted);
    }

    .tool-list {
      overflow-y: auto;
      flex: 1;
      padding: 8px;
    }

    .tool-item {
      padding: 9px 12px;
      border-radius: 6px;
      cursor: pointer;
      font-size: 13px;
      color: var(--text-muted);
      transition: background 0.1s, color 0.1s;
      word-break: break-all;
    }

    .tool-item:hover { background: var(--surface2); color: var(--text); }
    .tool-item.active { background: var(--accent); color: #fff; }

    .tool-list-loading {
      padding: 16px;
      font-size: 13px;
      color: var(--text-muted);
      text-align: center;
    }

    .content {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    .panel {
      flex: 1;
      display: flex;
      gap: 0;
      overflow: hidden;
    }

    .form-panel {
      flex: 1;
      padding: 24px;
      overflow-y: auto;
      border-right: 1px solid var(--border);
      min-width: 0;
    }

    .tool-title {
      font-size: 18px;
      font-weight: 600;
      margin-bottom: 6px;
    }

    .tool-description {
      font-size: 13px;
      color: var(--text-muted);
      margin-bottom: 24px;
      line-height: 1.5;
    }

    .empty-state {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;
      color: var(--text-muted);
      gap: 8px;
    }

    .empty-state .icon { font-size: 40px; }
    .empty-state p { font-size: 14px; }

    .field-group { margin-bottom: 18px; }

    .field-label {
      display: flex;
      align-items: center;
      gap: 6px;
      font-size: 13px;
      font-weight: 500;
      margin-bottom: 6px;
    }

    .field-label .optional {
      font-size: 11px;
      color: var(--text-muted);
      font-weight: 400;
    }

    .field-label .type-badge {
      font-size: 10px;
      font-family: var(--mono);
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 4px;
      padding: 1px 5px;
      color: var(--text-muted);
    }

    .field-desc {
      font-size: 12px;
      color: var(--text-muted);
      margin-bottom: 6px;
      line-height: 1.4;
    }

    input[type="text"], textarea, select {
      width: 100%;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      color: var(--text);
      font-family: var(--font);
      font-size: 13px;
      padding: 9px 12px;
      outline: none;
      transition: border-color 0.15s;
    }

    input[type="text"]:focus, textarea:focus, select:focus { border-color: var(--accent); }

    textarea {
      font-family: var(--mono);
      font-size: 12px;
      resize: vertical;
      min-height: 80px;
    }

    select option { background: var(--surface2); }

    .submit-btn {
      background: var(--accent);
      color: #fff;
      border: none;
      border-radius: var(--radius);
      padding: 10px 24px;
      font-size: 14px;
      font-weight: 600;
      cursor: pointer;
      transition: background 0.15s, opacity 0.15s;
      margin-top: 8px;
    }

    .submit-btn:hover { background: var(--accent-hover); }
    .submit-btn:disabled { opacity: 0.5; cursor: not-allowed; }

    .response-panel {
      flex: 1;
      padding: 24px;
      overflow-y: auto;
      min-width: 0;
      display: flex;
      flex-direction: column;
    }

    .response-header {
      font-size: 11px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.8px;
      color: var(--text-muted);
      margin-bottom: 12px;
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .response-status {
      font-size: 11px;
      padding: 2px 8px;
      border-radius: 10px;
      font-weight: 600;
    }

    .status-ok { background: var(--success-bg); color: #27ae60; border: 1px solid var(--success-border); }
    .status-err { background: var(--error-bg); color: var(--error-text); border: 1px solid var(--error-border); }

    .response-body {
      flex: 1;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 16px;
      font-family: var(--mono);
      font-size: 12px;
      line-height: 1.6;
      white-space: pre-wrap;
      word-break: break-all;
      overflow-y: auto;
      min-height: 200px;
    }

    .response-body.is-error {
      background: var(--error-bg);
      border-color: var(--error-border);
      color: var(--error-text);
    }

    .response-empty { color: var(--text-muted); font-style: italic; }

    .spinner {
      display: inline-block;
      width: 14px; height: 14px;
      border: 2px solid var(--border);
      border-top-color: var(--accent);
      border-radius: 50%;
      animation: spin 0.6s linear infinite;
      vertical-align: middle;
    }

    @keyframes spin { to { transform: rotate(360deg); } }

    ::-webkit-scrollbar { width: 6px; height: 6px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
    ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

    @media (max-width: 768px) {
      aside { width: 200px; }
      .panel { flex-direction: column; }
      .form-panel { border-right: none; border-bottom: 1px solid var(--border); }
      .api-key-group input { width: 200px; }
    }
  </style>
</head>
<body>

<header>
  <div class="logo">u6u MCP <span>Server 測試界面</span></div>
  <div class="api-key-group">
    <label for="apiKey">API Key</label>
    <div class="key-status" id="keyStatus"></div>
    <input type="text" id="apiKey" placeholder="輸入 Bearer Token..." autocomplete="off" spellcheck="false">
  </div>
</header>

<main>
  <aside>
    <div class="sidebar-header">
      Tools
      <span class="tool-count" id="toolCount">—</span>
    </div>
    <div class="tool-list" id="toolList">
      <div class="tool-list-loading">載入中…</div>
    </div>
  </aside>

  <div class="content">
    <div class="panel">
      <div class="form-panel" id="formPanel">
        <div class="empty-state">
          <div class="icon">🔧</div>
          <p>從左側選擇一個工具</p>
        </div>
      </div>

      <div class="response-panel">
        <div class="response-header">
          Response
          <span class="response-status" id="responseStatus" style="display:none"></span>
        </div>
        <div class="response-body response-empty" id="responseBody">尚未發送請求</div>
      </div>
    </div>
  </div>
</main>

<script>
  const BASE_URL = '';
  let tools = [];
  let selectedTool = null;
  let reqId = 1;

  document.addEventListener('DOMContentLoaded', function() {
  const apiKeyInput = document.getElementById('apiKey');
  const keyStatus = document.getElementById('keyStatus');
  const toolList = document.getElementById('toolList');
  const toolCount = document.getElementById('toolCount');
  const formPanel = document.getElementById('formPanel');
  const responseBody = document.getElementById('responseBody');
  const responseStatus = document.getElementById('responseStatus');

  let loadToolsDebounce = null;
  apiKeyInput.addEventListener('input', () => {
    const key = apiKeyInput.value.trim();
    keyStatus.classList.toggle('active', key.length > 0);
    clearTimeout(loadToolsDebounce);
    if (key.length > 0) {
      loadToolsDebounce = setTimeout(loadTools, 400);
    } else {
      toolList.innerHTML = '<div class="tool-list-loading">請先輸入 API Key</div>';
      toolCount.textContent = '—';
      tools = [];
    }
  });

  function getHeaders() {
    const h = {
      'Content-Type': 'application/json',
      'Accept': 'application/json, text/event-stream'
    };
    const key = apiKeyInput.value.trim();
    if (key) h['Authorization'] = 'Bearer ' + key;
    return h;
  }

  async function loadTools() {
    try {
      const res = await fetch(BASE_URL + '/mcp', {
        method: 'POST',
        headers: getHeaders(),
        body: JSON.stringify({ jsonrpc: '2.0', id: reqId++, method: 'tools/list', params: {} })
      });
      const text = await res.text();
      const data = parseMcpResponse(text);
      tools = (data.result && data.result.tools) || [];
      renderToolList();
    } catch (e) {
      toolList.innerHTML = '<div class="tool-list-loading" style="color:#ff6b6b">載入失敗：' + e.message + '</div>';
    }
  }

  function parseMcpResponse(text) {
    const dataLine = text.split('\\n').find(function(l) { return l.startsWith('data: '); });
    if (dataLine) {
      try { return JSON.parse(dataLine.slice(6)); } catch(e) {}
    }
    try { return JSON.parse(text); } catch(e) {}
    return {};
  }

  function renderToolList() {
    toolCount.textContent = tools.length;
    if (!tools.length) {
      toolList.innerHTML = '<div class="tool-list-loading">無可用工具</div>';
      return;
    }
    toolList.innerHTML = tools.map((t, i) =>
      '<div class="tool-item" data-index="' + i + '">' + escHtml(t.name) + '</div>'
    ).join('');
    toolList.querySelectorAll('.tool-item').forEach(el => {
      el.addEventListener('click', () => selectTool(parseInt(el.dataset.index)));
    });
  }

  function selectTool(index) {
    selectedTool = tools[index];
    toolList.querySelectorAll('.tool-item').forEach((el, i) => {
      el.classList.toggle('active', i === index);
    });
    renderForm(selectedTool);
    clearResponse();
  }

  function renderForm(tool) {
    const schema = tool.inputSchema || {};
    const props = schema.properties || {};
    const required = schema.required || [];

    let html = '<div class="tool-title">' + escHtml(tool.name) + '</div>';
    if (tool.description) {
      html += '<div class="tool-description">' + escHtml(tool.description) + '</div>';
    }

    const keys = Object.keys(props);
    if (keys.length === 0) {
      html += '<p style="color:var(--text-muted);font-size:13px;margin-bottom:16px;">此工具無需輸入參數</p>';
    } else {
      keys.forEach(key => {
        const prop = props[key];
        const isRequired = required.includes(key);
        const type = prop.type || 'string';
        const fieldId = 'field_' + key;

        html += '<div class="field-group">';
        html += '<div class="field-label">';
        html += '<label for="' + fieldId + '">' + escHtml(key) + '</label>';
        html += '<span class="type-badge">' + escHtml(type) + '</span>';
        if (!isRequired) html += '<span class="optional">(optional)</span>';
        html += '</div>';

        if (prop.description) {
          html += '<div class="field-desc">' + escHtml(prop.description) + '</div>';
        }

        html += renderField(fieldId, key, prop, type);
        html += '</div>';
      });
    }

    html += '<button class="submit-btn" id="submitBtn" onclick="submitTool()">送出請求</button>';
    formPanel.innerHTML = html;
  }

  function renderField(id, key, prop, type) {
    if (type === 'string' && prop.enum && prop.enum.length > 0) {
      let opts = prop.enum.map(v =>
        '<option value="' + escAttr(v) + '">' + escHtml(v) + '</option>'
      ).join('');
      return '<select id="' + id + '" data-key="' + escAttr(key) + '" data-type="enum">' + opts + '</select>';
    }
    if (type === 'array') {
      return '<textarea id="' + id + '" data-key="' + escAttr(key) + '" data-type="array" placeholder="[&quot;item1&quot;,&quot;item2&quot;]"></textarea>';
    }
    if (type === 'object') {
      return '<textarea id="' + id + '" data-key="' + escAttr(key) + '" data-type="object" placeholder="{&quot;key&quot;:&quot;value&quot;}"></textarea>';
    }
    return '<input type="text" id="' + id + '" data-key="' + escAttr(key) + '" data-type="string" placeholder="' + escAttr(prop.description || '') + '">';
  }

  async function submitTool() {
    if (!selectedTool) return;

    const btn = document.getElementById('submitBtn');
    btn.disabled = true;
    btn.innerHTML = '<span class="spinner"></span> 送出中…';

    const schema = selectedTool.inputSchema || {};
    const props = schema.properties || {};
    const required = schema.required || [];
    const args = {};
    let valid = true;

    Object.keys(props).forEach(key => {
      const el = document.getElementById('field_' + key);
      if (!el) return;
      const dtype = el.dataset.type;
      const raw = el.value.trim();

      if (!raw) {
        if (required.includes(key)) {
          el.style.borderColor = 'var(--error-border)';
          valid = false;
        }
        return;
      }

      el.style.borderColor = '';

      if (dtype === 'array' || dtype === 'object') {
        try {
          args[key] = JSON.parse(raw);
        } catch {
          el.style.borderColor = 'var(--error-border)';
          valid = false;
        }
      } else {
        args[key] = raw;
      }
    });

    if (!valid) {
      btn.disabled = false;
      btn.textContent = '送出請求';
      showResponse({ error: { message: '請修正標紅的欄位（必填或 JSON 格式錯誤）' } }, false);
      return;
    }

    const payload = {
      jsonrpc: '2.0',
      id: reqId++,
      method: 'tools/call',
      params: { name: selectedTool.name, arguments: args }
    };

    try {
      const res = await fetch(BASE_URL + '/mcp', {
        method: 'POST',
        headers: getHeaders(),
        body: JSON.stringify(payload)
      });
      const text = await res.text();
      const data = parseMcpResponse(text);
      const isError = (data.result && data.result.isError) || !!data.error;
      showResponse(data, isError);
    } catch (e) {
      showResponse({ error: { message: e.message } }, true);
    } finally {
      btn.disabled = false;
      btn.textContent = '送出請求';
    }
  }

  function showResponse(data, isError) {
    responseBody.textContent = JSON.stringify(data, null, 2);
    responseBody.classList.toggle('is-error', isError);
    responseBody.classList.remove('response-empty');

    responseStatus.style.display = '';
    if (isError) {
      responseStatus.textContent = 'Error';
      responseStatus.className = 'response-status status-err';
    } else {
      responseStatus.textContent = 'OK';
      responseStatus.className = 'response-status status-ok';
    }
  }

  function clearResponse() {
    responseBody.textContent = '尚未發送請求';
    responseBody.classList.remove('is-error');
    responseBody.classList.add('response-empty');
    responseStatus.style.display = 'none';
  }

  function escHtml(s) {
    return String(s)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;');
  }

  function escAttr(s) {
    return String(s).replace(/"/g, '&quot;').replace(/'/g, '&#39;');
  }

  // Don't auto-load on page open — wait for API Key input
  toolList.innerHTML = '<div class="tool-list-loading">請先輸入 API Key</div>';
  window.submitTool = submitTool;
  }); // end DOMContentLoaded
<\/script>
</body>
</html>`;
