const app = document.getElementById('app');
let payload = null;

const labels = {
  zh: {
    copied: '复制',
    copyRaw: '复制原文',
    copyJson: '复制 JSON',
    openSafe: '安全浏览器',
    openSystem: '系统浏览器',
    openFolder: '打开文件夹',
    raw: '原始输出',
    details: '详情',
    emptyTitle: '暂无结构化结果',
    emptyText: '工具运行后，整理后的卡片会显示在这里。',
    blocks: '区块',
    lines: '行数',
    chars: '字符',
    mode: '模式',
    media: '媒体预览',
    file: '文件结果',
    link: '链接'
  },
  en: {
    copied: 'Copy',
    copyRaw: 'Copy raw',
    copyJson: 'Copy JSON',
    openSafe: 'Safe browser',
    openSystem: 'System browser',
    openFolder: 'Open folder',
    raw: 'Raw output',
    details: 'Details',
    emptyTitle: 'No structured result',
    emptyText: 'Structured cards will appear here after the tool runs.',
    blocks: 'Blocks',
    lines: 'Lines',
    chars: 'Chars',
    mode: 'Mode',
    media: 'Media preview',
    file: 'File result',
    link: 'Link'
  }
};

window.chrome?.webview?.addEventListener('message', event => receive(event.data));

window.addEventListener('message', event => {
  if (receive(event.data)) return;
  if (event.data?.type === 'tool-result-payload') {
    payload = event.data.payload;
    render(payload);
  }
});

function receive(data) {
  if (!data) return false;
  if (data.type === 'performanceMode') {
    document.documentElement.classList.toggle('drag-light', !!data.lightMode);
    document.documentElement.classList.toggle('drag-strong', !!data.lightMode && data.level === 'strong');
    return true;
  }

  if (data.type) return false;
  payload = data;
  render(payload);
  return true;
}

function isEnglish() {
  return (payload?.language || '').toLowerCase().startsWith('en');
}

function t(key) {
  return (isEnglish() ? labels.en : labels.zh)[key] || labels.en[key] || key;
}

function post(action, value) {
  window.chrome?.webview?.postMessage({ action, value });
}

function text(value) {
  return value === null || value === undefined ? '' : String(value);
}

function el(tag, className, content) {
  const node = document.createElement(tag);
  if (className) node.className = className;
  if (content !== undefined) node.textContent = content;
  return node;
}

function render(data) {
  if (!data) return;
  const theme = (data.theme || '').toLowerCase().includes('dark') ? 'dark' : 'light';
  document.documentElement.dataset.theme = theme;
  document.documentElement.lang = (data.language || '').toLowerCase().startsWith('en') ? 'en-US' : 'zh-CN';
  document.documentElement.style.setProperty('--accent', data.experience?.accent || '#2563eb');

  app.innerHTML = '';
  const root = el('section', 'result-page');
  root.append(chrome(data));

  const blocks = el('section', 'blocks');
  for (const block of (data.resultDocument?.blocks || [])) {
    blocks.append(renderBlock(block, data));
  }
  if (!blocks.childElementCount) {
    blocks.append(emptyBlock(data));
  }
  root.append(blocks, detailsDrawer(data));
  app.append(root);
}

function chrome(data) {
  const root = el('section', 'result-chrome');
  const identity = el('div', 'identity');
  const mark = el('div', 'mark', (data.toolName || data.toolId || 'T').trim().slice(0, 2).toUpperCase());
  const title = el('div', 'title');
  title.append(el('h1', '', data.toolName || data.toolId || 'Tool result'));
  title.append(el('p', 'meta', `${data.experience?.primaryPrimitive || data.experience?.layout || 'result'} / ${data.runtimeMetadata?.durationMs ?? 0} ms`));
  identity.append(mark, title);

  const actions = el('div', 'actions');
  actions.append(button(t('copyRaw'), () => post('copy', data.resultDocument?.rawText || '')));
  actions.append(button(t('copyJson'), () => post('copy', JSON.stringify(data.resultDocument || {}, null, 2)), 'ghost'));

  root.append(identity, actions, metrics(data));
  return root;
}

function metrics(data) {
  const doc = data.resultDocument || {};
  const raw = doc.rawText || '';
  const rows = raw ? raw.replace(/\r\n/g, '\n').split('\n').length : 0;
  const values = [
    [t('blocks'), (doc.blocks || []).length],
    [t('lines'), rows],
    [t('chars'), raw.length],
    [t('mode'), data.experience?.primaryPrimitive || 'custom']
  ];
  const root = el('section', 'metrics');
  for (const [label, value] of values) {
    const metric = el('div', 'metric');
    metric.append(el('span', 'muted', label), el('strong', '', value));
    root.append(metric);
  }
  return root;
}

function renderBlock(block, data) {
  const kind = (block.kind || '').toLowerCase();
  const root = el('article', `block kind-${kind || 'text'}`);
  const head = el('div', 'block-head');
  const title = el('div', 'block-title');
  title.append(blockIcon(kind), el('h2', '', block.title || kindLabel(kind)));
  head.append(title, el('span', 'badge', kindLabel(kind)));
  root.append(head);

  if (kind === 'keyvalue' || kind === 'metric') root.append(kvGrid(block.pairs || [], data, kind));
  else if (kind === 'table' || kind === 'linechart') root.append(table(block.rows || [], data));
  else if (['rankedlist', 'newslist', 'cardlist'].includes(kind)) root.append(list(block.items || [], data, kind));
  else if (['text', 'diff', 'status', 'timeline'].includes(kind)) root.append(statusList(block.items || [], data, block.text));
  else if (['code', 'json', 'jsontree', 'raw'].includes(kind)) root.append(code(redact(block.text || '', data.privacyPolicy)));
  else if (kind === 'file') root.append(fileBlock(block, data));
  else if (kind === 'link') root.append(linkBlock(block, data));
  else if (kind === 'image' || kind === 'media') root.append(mediaBlock(block, data));
  else if (kind === 'color') root.append(colorBlock(block));
  else root.append(el('p', 'paragraph', redact(block.text || '', data.privacyPolicy)));
  return root;
}

function kvGrid(pairs, data, kind) {
  const grid = el('div', `kv-grid ${kind === 'metric' ? 'metric-grid' : ''}`);
  for (const [index, pair] of pairs.slice(0, 80).entries()) {
    const item = el('div', `kv ${index === 0 && kind === 'metric' ? 'primary-kv' : ''}`);
    item.append(el('span', '', pair.key || ''), el('strong', '', redact(pair.value || '', data.privacyPolicy)));
    grid.append(item);
  }
  if (!pairs.length) grid.append(el('p', 'muted', t('emptyText')));
  return grid;
}

function table(rows, data) {
  const wrap = el('div', 'table-wrap');
  const tableNode = el('table');
  for (const [rowIndex, row] of rows.slice(0, 180).entries()) {
    const tr = el('tr');
    const cells = Array.isArray(row) ? row : Object.values(row || {});
    for (const cell of cells.slice(0, 8)) tr.append(el(rowIndex === 0 ? 'th' : 'td', '', redact(cell, data.privacyPolicy)));
    tableNode.append(tr);
  }
  if (!rows.length) {
    const tr = el('tr');
    tr.append(el('td', 'muted', t('emptyText')));
    tableNode.append(tr);
  }
  wrap.append(tableNode);
  return wrap;
}

function list(items, data, kind) {
  const root = el('div', `list ${kind === 'rankedlist' ? 'ranked-list' : 'card-list'} ${kind}`);
  for (const [index, item] of items.slice(0, 220).entries()) {
    const normalized = normalizeListItem(item, index);
    const row = el('div', `list-item ${kind === 'rankedlist' ? 'ranked-item' : ''}`);
    row.append(rankBadge(normalized.rank, normalized.leading, kind));
    const body = el('div', 'item-body');
    body.append(el('strong', '', redact(normalized.title, data.privacyPolicy)));
    if (normalized.subtitle) body.append(el('span', 'item-subtitle', redact(normalized.subtitle, data.privacyPolicy)));
    row.append(body);
    makeCardLink(row, normalized.uri, normalized.title);
    root.append(row);
  }
  if (!items.length) root.append(el('p', 'muted', t('emptyText')));
  return root;
}

function statusList(items, data, fallbackText) {
  if (!items.length) return code(redact(fallbackText || '', data.privacyPolicy));
  const root = el('div', 'list status-list');
  for (const [index, item] of items.slice(0, 220).entries()) {
    const normalized = normalizeListItem(item, index);
    const row = el('div', `list-item status-${normalized.status || 'info'}`);
    row.append(el('span', 'badge', normalized.leading));
    const body = el('div', 'item-body');
    body.append(el('strong', '', redact(normalized.title, data.privacyPolicy)));
    if (normalized.subtitle) body.append(el('span', 'item-subtitle', redact(normalized.subtitle, data.privacyPolicy)));
    row.append(body);
    if (normalized.uri) row.append(linkActions(normalized.uri));
    root.append(row);
  }
  return root;
}

function normalizeListItem(item, index) {
  let title = text(item?.title || item?.text || t('emptyTitle'));
  let subtitle = text(item?.subtitle || '');
  const leading = text(item?.leading || item?.status || index + 1);
  const rank = Number.parseInt(leading, 10) || index + 1;
  const parts = title.split(/\s+\/\s+/).filter(Boolean);
  if (parts.length > 1) {
    title = parts[0];
    subtitle = subtitle ? `${subtitle}\n${parts.slice(1).join(' / ')}` : parts.slice(1).join(' / ');
  }
  return {
    rank,
    leading,
    title,
    subtitle,
    uri: text(item?.uri || ''),
    status: text(item?.status || '')
  };
}

function rankBadge(rank, label, kind) {
  const badge = el('span', `rank-badge rank-${rank <= 3 && kind === 'rankedlist' ? rank : 'other'} ${kind !== 'rankedlist' ? 'plain' : ''}`);
  badge.append(el('span', 'rank-core', rank <= 3 && kind === 'rankedlist' ? String(rank) : label));
  return badge;
}

function linkActions(uri) {
  const actions = el('div', 'link-actions');
  actions.append(button(t('openSafe'), () => post('openLink', uri)));
  actions.append(button(t('openSystem'), () => post('openSystemBrowser', uri), 'ghost compact'));
  return actions;
}

function makeCardLink(row, uri, label) {
  if (!uri) return;
  row.classList.add('clickable');
  row.tabIndex = 0;
  row.role = 'link';
  row.title = uri;
  row.setAttribute('aria-label', `${t('openSafe')} ${label || uri}`);
  row.addEventListener('click', event => {
    event.preventDefault();
    post('openLink', uri);
  });
  row.addEventListener('keydown', event => {
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      post('openLink', uri);
    }
  });
}

function code(value) {
  const wrap = el('div', 'code-wrap');
  const pre = el('pre');
  pre.textContent = value;
  wrap.append(pre);
  return wrap;
}

function fileBlock(block, data) {
  const row = el('div', 'list-item file-card');
  row.append(el('span', 'badge', 'FILE'));
  const body = el('div', 'item-body');
  body.append(el('strong', '', block.text || block.path || t('file')));
  body.append(el('span', '', redact(block.path || '', data.privacyPolicy)));
  row.append(body, button(t('openFolder'), () => post('openFolder', block.path)));
  return row;
}

function linkBlock(block, data) {
  const row = el('div', 'list-item link-card');
  row.append(el('span', 'badge', 'URL'));
  const body = el('div', 'item-body');
  body.append(el('strong', '', redact(block.text || block.uri || t('link'), data.privacyPolicy)));
  body.append(el('span', '', redact(block.uri || '', data.privacyPolicy)));
  row.append(body, linkActions(block.uri));
  return row;
}

function mediaBlock(block, data) {
  const uri = block.uri || block.text || '';
  const metadata = block.metadata || {};
  const pngBase64 = metadata.pngBase64 || metadata.pngbase64 || '';
  const rawSvg = metadata.rawSvg || metadata.rawsvg || (String(uri).trim().startsWith('<svg') ? uri : '');
  const source = pngBase64
    ? `data:image/png;base64,${pngBase64}`
    : rawSvg
      ? `data:image/svg+xml;charset=utf-8,${encodeURIComponent(rawSvg)}`
      : uri;
  if (/\.(png|jpe?g|gif|webp|bmp|svg)(\?|$)/i.test(source) || source.startsWith('data:image')) {
    const frame = el('div', 'media-frame');
    const img = new Image();
    img.alt = block.title || t('media');
    img.loading = 'eager';
    img.decoding = 'async';
    img.src = source;
    frame.append(img);
    return frame;
  }
  return linkBlock(block, data);
}

function colorBlock(block) {
  const swatch = el('div', 'swatch');
  swatch.style.background = block.text || block.uri || payload?.experience?.accent || '#2563eb';
  return swatch;
}

function detailsDrawer(data) {
  const root = el('details', 'details-drawer');
  const summary = el('summary');
  summary.append(el('span', '', t('details')));
  summary.append(el('span', 'muted', data.experienceId || data.experience?.layout || 'result'));
  root.append(summary);
  root.append(rawCard(data));
  return root;
}

function rawCard(data) {
  const root = el('section', 'raw-card');
  const head = el('div', 'block-head');
  head.append(el('h2', '', t('raw')), button(t('copyRaw'), event => {
    event.preventDefault?.();
    event.stopPropagation?.();
    post('copy', data.resultDocument?.rawText || '');
  }, 'ghost compact'));
  root.append(head, code(redact(data.resultDocument?.rawText || '', data.privacyPolicy)));
  return root;
}

function emptyBlock(data) {
  const root = el('article', 'block empty-card');
  root.append(el('h2', '', t('emptyTitle')));
  root.append(el('p', 'muted', t('emptyText')));
  const raw = data.resultDocument?.rawText || '';
  if (raw) root.append(code(redact(raw, data.privacyPolicy)));
  return root;
}

function redact(value, policy = payload?.privacyPolicy) {
  let output = text(value);
  for (const hint of policy?.redactedHostHints || []) {
    const escaped = String(hint).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    output = output.replace(new RegExp(`https?://[^\\s"'<>]*${escaped}[^\\s"'<>]*`, 'gi'), isEnglish() ? '[YMhut endpoint hidden]' : '[YMhut 接口已隐藏]');
  }
  return output;
}

function kindLabel(kind) {
  const key = String(kind || '').toLowerCase();
  const zh = {
    keyvalue: '详情',
    metric: '指标',
    table: '表格',
    linechart: '趋势',
    rankedlist: '排行',
    newslist: '新闻',
    cardlist: '卡片',
    timeline: '时间线',
    status: '状态',
    diff: '差异',
    text: '文本',
    code: '代码',
    json: 'JSON',
    jsontree: 'JSON',
    raw: '原文',
    file: '文件',
    link: '链接',
    image: '图像',
    media: '媒体',
    color: '颜色'
  };
  const en = {
    keyvalue: 'Details',
    metric: 'Metric',
    table: 'Table',
    linechart: 'Trend',
    rankedlist: 'Ranking',
    newslist: 'News',
    cardlist: 'Cards',
    timeline: 'Timeline',
    status: 'Status',
    diff: 'Diff',
    text: 'Text',
    code: 'Code',
    json: 'JSON',
    jsontree: 'JSON',
    raw: 'Raw',
    file: 'File',
    link: 'Link',
    image: 'Image',
    media: 'Media',
    color: 'Color'
  };
  const lang = isEnglish() ? en : zh;
  return lang[key] || key || t('details');
}

function blockIcon(kind) {
  const node = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  node.setAttribute('class', 'block-icon');
  node.setAttribute('viewBox', '0 0 24 24');
  node.setAttribute('aria-hidden', 'true');
  const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  path.setAttribute('fill', 'none');
  path.setAttribute('stroke', 'currentColor');
  path.setAttribute('stroke-width', '1.8');
  path.setAttribute('stroke-linecap', 'round');
  path.setAttribute('stroke-linejoin', 'round');
  path.setAttribute('d', {
    rankedlist: 'M7 17h10M8 13h8M10 9h4M12 4l2 3 3 .5-2.2 2.1.5 3.2L12 11l-3.3 1.8.5-3.2L7 7.5 10 7z',
    newslist: 'M5 5h14v14H5zM8 9h8M8 13h8M8 17h5',
    table: 'M4 5h16v14H4zM4 11h16M10 5v14',
    link: 'M10 13a5 5 0 0 0 7.1 0l1.4-1.4a5 5 0 0 0-7.1-7.1L10.7 5M14 11a5 5 0 0 0-7.1 0l-1.4 1.4a5 5 0 0 0 7.1 7.1l.7-.7',
    file: 'M6 3h8l4 4v14H6zM14 3v5h5',
    media: 'M4 7h16v10H4zM9 10l5 2-5 2z',
    image: 'M4 5h16v14H4zM8 14l2-2 3 3 2-2 3 4',
    status: 'M5 12l4 4L19 6',
    code: 'M9 18l-6-6 6-6M15 6l6 6-6 6',
    json: 'M8 5H6v14h2M16 5h2v14h-2',
    jsontree: 'M8 5H6v14h2M16 5h2v14h-2',
    color: 'M12 3a9 9 0 0 0 0 18 3 3 0 0 0 3-3c0-1.7-1.3-3-3-3H9a6 6 0 0 1 3-12z',
    default: 'M5 7h14M5 12h14M5 17h10'
  }[kind] || 'M5 7h14M5 12h14M5 17h10');
  node.append(path);
  return node;
}

function button(label, onClick, className = '') {
  const node = el('button', className, label);
  node.type = 'button';
  node.addEventListener('click', onClick);
  return node;
}
