import { SRC, SRC_DEFAULT, MSG, CODEX_TAGS, COMPACTION_SIG, INTERRUPTION_CLAUDE_SIG, INTERRUPTION_CODEX_SIG } from './constants.js';
import { escapeHtml } from './utils.js';

export function isCompaction(m) {
  return m.type === 'user' && m.content && m.content.startsWith(COMPACTION_SIG);
}

export function isInterruption(m) {
  return (m.type === 'tool_result' && m.result && m.result.output && m.result.output.includes(INTERRUPTION_CLAUDE_SIG))
    || (m.type === 'user' && m.content && m.content.startsWith(INTERRUPTION_CODEX_SIG));
}

export function parseTaggedSections(text) {
  const tagRegex = /<([a-zA-Z_][a-zA-Z0-9_ -]*)>([\s\S]*?)<\/\1>/g;
  const sections = [];
  let lastIndex = 0;
  const plainParts = [];
  let match;
  while ((match = tagRegex.exec(text)) !== null) {
    if (match.index > lastIndex) plainParts.push(text.slice(lastIndex, match.index));
    const tagName = match[1].trim();
    const isCodex = CODEX_TAGS.has(tagName) || CODEX_TAGS.has(tagName.replace(/\s+/g, '_'));
    sections.push({ tag: tagName, body: match[2].trim(), isCodex });
    lastIndex = match.index + match[0].length;
  }
  if (lastIndex < text.length) plainParts.push(text.slice(lastIndex));
  return { plain: plainParts.join('').trim(), sections };
}

export function makeCollapsible(label, body, btnClass, bodyClass) {
  const id = 'c-' + Math.random().toString(36).slice(2, 8);
  return `<div class="mt-1.5">
    <button class="tag-toggle inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-semibold uppercase tracking-wide ${btnClass} transition-colors" data-collapse-id="${id}">
      <span class="arrow text-[8px]">&#9654;</span>${label}
    </button>
    <div class="tag-body mt-1 px-3 py-2 rounded-lg text-[11px] font-mono whitespace-pre-wrap break-words max-h-96 overflow-y-auto leading-relaxed ${bodyClass}" id="${id}">${escapeHtml(body)}</div>
  </div>`;
}

export function renderContent(content) {
  if (!content) return '';
  const { plain, sections } = parseTaggedSections(content);
  let html = '';
  if (plain) html += `<div class="text-[13px] text-gray-600 leading-relaxed whitespace-pre-wrap break-words mt-1.5">${escapeHtml(plain)}</div>`;
  for (const s of sections) {
    const lbl = s.isCodex
      ? `${s.tag} <span class="text-[8px] opacity-60 font-normal normal-case ml-1">codex</span>`
      : s.tag;
    const btnCls = s.isCodex
      ? 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200'
      : 'bg-gray-100 text-gray-500 hover:bg-gray-200';
    html += makeCollapsible(lbl, s.body, btnCls, 'bg-gray-50 border border-gray-100');
  }
  return html;
}

export function renderSessionHeader(msgs, source, sessionId, lastCompactJump) {
  const src = SRC[source] || SRC_DEFAULT;
  const first = msgs[0].timestamp.slice(0, 16).replace('T', ' ');
  const last = msgs[msgs.length - 1].timestamp.slice(0, 16).replace('T', ' ');
  const userCount = msgs.filter(m => m.type === 'user').length;
  const toolCount = msgs.filter(m => m.type === 'tool_call').length;
  const compactCount = msgs.filter(isCompaction).length;
  const interruptCount = msgs.filter(isInterruption).length;

  return `<div class="flex items-center gap-2 flex-wrap">
      <span class="text-[10px] font-medium px-1.5 py-0.5 rounded ${src.badge}">${src.label}</span>
      <span class="text-xs text-gray-700 font-semibold">${msgs.length} msgs</span>
      <span class="text-[10px] text-gray-400">${userCount} prompts &middot; ${toolCount} tools</span>
      ${compactCount ? `<span class="compaction-badge cursor-pointer hover:bg-amber-100" data-action="jump-compact" title="Click to jump to compaction point">&#9889; ${compactCount} compact${compactCount > 1 ? 's' : ''}</span>` : ''}
      ${interruptCount ? `<span class="interruption-badge cursor-pointer hover:bg-red-100" data-action="jump-interrupt" title="Click to jump to interruption point"><span class="inline-block w-1.5 h-1.5 rounded-full bg-red-500"></span> ${interruptCount} interrupt${interruptCount > 1 ? 's' : ''}</span>` : ''}
      <span class="text-[10px] text-gray-300 font-mono ml-auto">${first} &rarr; ${last}</span>
      <button data-action="copy-session-id" data-session-id="${sessionId}" class="text-[10px] text-gray-400 hover:text-[#009689] font-mono px-1.5 py-0.5 rounded hover:bg-[#f0fdfa] transition-colors cursor-pointer" title="Click to copy session ID">${sessionId.slice(0, 8)}</button>
      <span class="text-gray-200">|</span>
      <div class="relative inline-block" id="export-wrap">
        <button data-action="toggle-export" class="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-medium text-gray-500 bg-gray-100 hover:bg-gray-200 transition-colors">
          Export <span class="text-[8px]">&#9660;</span>
        </button>
        <div id="export-menu" class="hidden absolute right-0 top-full mt-1 bg-white rounded-lg shadow-xl border border-gray-200 py-1 z-30 w-52">
          <div class="px-3 py-1 text-[9px] font-semibold text-gray-400 uppercase tracking-wider">Copy to clipboard</div>
          <button data-action="export" data-mode="clipboard" data-filter="user" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-blue-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-blue-400"></span> User messages
          </button>
          <button data-action="export" data-mode="clipboard" data-filter="assistant" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-emerald-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span> Assistant messages
          </button>
          <button data-action="export" data-mode="clipboard" data-filter="conversation" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-gray-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-gray-400"></span> User + Assistant
          </button>
          <button data-action="export" data-mode="clipboard" data-filter="all" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-gray-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-violet-400"></span> Everything
          </button>
          <div class="border-t border-gray-100 my-0.5"></div>
          <div class="px-3 py-1 text-[9px] font-semibold text-gray-400 uppercase tracking-wider">Download JSON</div>
          <button data-action="export" data-mode="json" data-filter="user" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-blue-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-blue-400"></span> User messages
          </button>
          <button data-action="export" data-mode="json" data-filter="assistant" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-emerald-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span> Assistant messages
          </button>
          <button data-action="export" data-mode="json" data-filter="conversation" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-gray-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-gray-400"></span> User + Assistant
          </button>
          <button data-action="export" data-mode="json" data-filter="all" class="w-full text-left px-3 py-1 text-[11px] text-gray-700 hover:bg-gray-50 flex items-center gap-2">
            <span class="w-1.5 h-1.5 rounded-full bg-violet-400"></span> Full session
          </button>
        </div>
      </div>
    </div>`;
}

export function renderMessagesHtml(msgs, source, sessionId) {
  let html = '<div class="flex flex-col gap-1">';

  let compactIdx = 0;
  let interruptIdx = 0;
  for (const m of msgs) {
    if (m.type === 'progress') continue;
    if (m.type === 'tool_call' && !m.content && (!m.tool || !m.tool.tool_input)) continue;

    // Interruption breakpoint
    if (isInterruption(m)) {
      interruptIdx++;
      const time = m.timestamp.slice(11, 19);
      html += `<div class="interruption-break" id="interrupt-${interruptIdx}"><span class="interruption-badge"><span class="inline-block w-1.5 h-1.5 rounded-full bg-red-500"></span> User interrupted <span class="text-[9px] font-mono text-red-500">${time}</span></span></div>`;
    }

    // Compaction breakpoint
    if (isCompaction(m)) {
      compactIdx++;
      const time = m.timestamp.slice(11, 19);
      const isFirst = compactIdx === 1 && msgs.indexOf(m) === 0;
      const label = isFirst ? 'Resumed from previous session' : 'Context compacted';
      html += `<div class="compaction-break" id="compact-${compactIdx}"><span class="compaction-badge">&#9889; ${label} <span class="text-[9px] font-mono text-amber-500">${time}</span></span></div>`;
      html += makeCollapsible('compaction summary', m.content,
        'bg-amber-100 text-amber-700 hover:bg-amber-200',
        'bg-amber-50/50 border border-amber-200');
      continue;
    }

    const time = m.timestamp.slice(11, 19);
    const st = MSG[m.type] || MSG.system;

    html += `<div class="${st.bg} border-l-[3px] ${st.border} rounded-r-lg px-3 py-2" data-msgtype="${m.type}">`;
    html += `<div class="flex items-center gap-2 flex-wrap">
      <span class="text-[11px] text-gray-400 font-mono">${time}</span>
      <span class="text-[10px] font-bold uppercase tracking-wide ${st.label}">${m.type.replace('_', ' ')}</span>`;

    if (m.tool) html += `<span class="text-[11px] font-semibold text-amber-700 bg-amber-50 px-1.5 py-0.5 rounded">${escapeHtml(m.tool.tool_name)}</span>`;
    if (m.result) {
      const hasOutput = m.result.output && m.result.output.trim();
      const isOk = m.result.status === 'success';
      if (!hasOutput && isOk) {
        html += `<span class="text-[10px] font-semibold text-slate-400">no output</span>`;
      } else {
        html += `<span class="text-[10px] font-semibold ${isOk ? 'text-emerald-600' : 'text-red-500'}">${isOk ? 'OK' : 'FAIL'}</span>`;
      }
    }
    html += `</div>`;

    html += renderContent(m.content);

    if (m.tool && m.tool.tool_input) {
      html += makeCollapsible('input', m.tool.tool_input,
        'bg-amber-100/80 text-amber-700 hover:bg-amber-200',
        'bg-amber-50/50 border border-amber-100');
    }
    if (m.result && m.result.output) {
      const isOk = m.result.status === 'success';
      html += makeCollapsible('output', m.result.output,
        isOk ? 'bg-slate-100 text-slate-500 hover:bg-slate-200' : 'bg-red-100 text-red-600 hover:bg-red-200',
        isOk ? 'bg-slate-50 border border-slate-100' : 'bg-red-50 border border-red-100');
    }

    html += `</div>`;
  }
  html += '</div>';
  return html;
}
