// ═══════════════════════════════════════════════════════
//  CVC Dashboard — Chat Module
//  (Compiled from ts/chat.ts — edit TypeScript source)
// ═══════════════════════════════════════════════════════
"use strict";

/** @type {{ role: string; content: string }[]} */
let chatHistory = [];
/** @type {boolean} */
let isStreaming = false;

function initChat() {
  const input = document.getElementById('chat-input');
  const sendBtn = document.getElementById('chat-send');
  const stopBtn = document.getElementById('chat-stop');

  // Auto-resize textarea
  input.addEventListener('input', () => {
    input.style.height = 'auto';
    input.style.height = Math.min(input.scrollHeight, 200) + 'px';
  });

  // Ctrl+Enter to send
  input.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      sendChatMessage();
    }
  });

  sendBtn.addEventListener('click', sendChatMessage);
  stopBtn.addEventListener('click', stopChatGeneration);

  // Suggestion buttons
  document.querySelectorAll('.suggestion-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      const msg = btn.dataset.msg;
      if (msg) {
        input.value = msg;
        sendChatMessage();
      }
    });
  });

  // Load current model tag
  loadChatModelTag();
}

async function loadChatModelTag() {
  try {
    const m = await CvcApi.getCurrentModel();
    const tag = document.getElementById('chat-model');
    if (tag) tag.textContent = m.model || m.provider || '—';
  } catch { /* ignore */ }
}

async function sendChatMessage() {
  if (isStreaming) return;
  const input = document.getElementById('chat-input');
  const text = input.value.trim();
  if (!text) return;

  input.value = '';
  input.style.height = 'auto';

  // Remove welcome screen
  const welcome = document.querySelector('.chat-welcome');
  if (welcome) welcome.remove();

  // Add user message
  const userMsg = { role: 'user', content: text };
  chatHistory.push(userMsg);
  appendChatMessage(userMsg);

  // Stream assistant response (with tool calls)
  isStreaming = true;
  toggleStopButton(true);
  const assistantMsg = { role: 'assistant', content: '' };
  chatHistory.push(assistantMsg);
  const msgEl = appendChatMessage(assistantMsg, true);
  const bodyEl = msgEl.querySelector('.chat-message-body');
  let contentEl = bodyEl.querySelector('.msg-content');

  try {
    const stream = CvcApi.chatStream({
      messages: chatHistory.slice(0, -1),
      stream: true,
    });

    for await (const event of stream) {
      if (event.type === 'text') {
        assistantMsg.content += event.content;
        renderChatMarkdown(contentEl, assistantMsg.content);
      } else if (event.type === 'tool_confirm') {
        // Permission request — show inline confirm/deny buttons
        const confirmCard = createToolConfirmCard(event.name, event.args);
        bodyEl.appendChild(confirmCard);
        scrollChatToBottom();
        // Wait for user decision
        const decision = await waitForToolConfirmation(confirmCard);
        await CvcApi.confirmTool(decision);
        // Update card to reflect decision
        markConfirmCardDecision(confirmCard, decision);
      } else if (event.type === 'tool_start') {
        // Render a collapsible tool card
        const card = createToolCard(event.name, event.args);
        bodyEl.appendChild(card);
      } else if (event.type === 'tool_result') {
        // Find the last tool card for this tool and fill in the result
        const cards = bodyEl.querySelectorAll(`.tool-card[data-tool="${event.name}"]`);
        const card = cards[cards.length - 1];
        if (card) {
          fillToolResult(card, event.output);
        }
      } else if (event.type === 'status') {
        // Show a transient status indicator
        showAgentStatus(bodyEl, event.message);
      }

      // After tool results, LLM continues — ensure there's a fresh
      // content element for the next text chunk
      if (event.type === 'tool_result') {
        contentEl = ensureFreshContentEl(bodyEl);
        assistantMsg.content = '';  // reset for the next text segment
      }

      scrollChatToBottom();
    }
  } catch (err) {
    assistantMsg.content += `\n\n_Error: ${err.message}_`;
    renderChatMarkdown(contentEl, assistantMsg.content);
  }

  // Remove streaming indicator
  const cursor = contentEl.querySelector('.streaming-indicator');
  if (cursor) cursor.remove();
  // Remove any leftover status badges
  bodyEl.querySelectorAll('.agent-status').forEach(s => s.remove());
  renderChatMarkdown(contentEl, assistantMsg.content);
  isStreaming = false;
  toggleStopButton(false);
  scrollChatToBottom();
}

/**
 * Toggle send/stop button visibility.
 * @param {boolean} streaming — true = show stop, false = show send
 */
function toggleStopButton(streaming) {
  const sendBtn = document.getElementById('chat-send');
  const stopBtn = document.getElementById('chat-stop');
  if (streaming) {
    sendBtn.classList.add('hidden');
    stopBtn.classList.remove('hidden');
  } else {
    stopBtn.classList.add('hidden');
    sendBtn.classList.remove('hidden');
  }
}

/**
 * Stop the running agentic chat loop.
 */
async function stopChatGeneration() {
  try {
    await CvcApi.abortChat();
  } catch { /* best effort */ }
}

// ── Tool Card helpers ───────────────────────────────────

/**
 * Create a collapsible tool card element.
 * @param {string} toolName
 * @param {object} args
 * @returns {HTMLElement}
 */
function createToolCard(toolName, args) {
  const card = document.createElement('div');
  card.className = 'tool-card';
  card.dataset.tool = toolName;

  const icon = getToolIcon(toolName);
  const argsPreview = Object.entries(args || {}).map(([k, v]) => `${k}: ${v}`).join(', ');

  card.innerHTML = `
    <div class="tool-card-header" onclick="this.parentElement.classList.toggle('expanded')">
      <span class="tool-icon">${icon}</span>
      <span class="tool-name">${escHtml(toolName)}</span>
      <span class="tool-args-preview">${escHtml(argsPreview).substring(0, 120)}</span>
      <span class="tool-spinner"></span>
      <span class="tool-chevron">&#9660;</span>
    </div>
    <div class="tool-card-body">
      <div class="tool-args"><strong>Arguments:</strong><pre>${escHtml(JSON.stringify(args, null, 2))}</pre></div>
      <div class="tool-output"><em>Running…</em></div>
    </div>
  `;
  return card;
}

/**
 * Fill in the result of a tool card.
 * @param {HTMLElement} card
 * @param {string} output
 */
function fillToolResult(card, output) {
  card.classList.add('completed');
  card.classList.remove('expanded');
  const spinner = card.querySelector('.tool-spinner');
  if (spinner) spinner.remove();
  const outputEl = card.querySelector('.tool-output');
  if (outputEl) {
    outputEl.innerHTML = `<strong>Output:</strong><pre>${escHtml(output)}</pre>`;
  }
}

/**
 * Show a status message below the current content.
 * @param {HTMLElement} bodyEl
 * @param {string} message
 */
function showAgentStatus(bodyEl, message) {
  // Remove previous status
  bodyEl.querySelectorAll('.agent-status').forEach(s => s.remove());
  const badge = document.createElement('div');
  badge.className = 'agent-status';
  badge.textContent = message;
  bodyEl.appendChild(badge);
}

/**
 * Ensure there's a fresh .msg-content element at the end of bodyEl for new text.
 * @param {HTMLElement} bodyEl
 * @returns {HTMLElement}
 */
function ensureFreshContentEl(bodyEl) {
  const el = document.createElement('div');
  el.className = 'msg-content';
  bodyEl.appendChild(el);
  return el;
}

/** Map tool name → icon. */
function getToolIcon(name) {
  const icons = {
    read_file: '📄', write_file: '✏️', edit_file: '✏️', patch_file: '🩹',
    bash: '🖥️', glob: '🔍', grep: '🔎', list_dir: '📁',
    web_search: '🌐', cvc_status: '📊', cvc_log: '📋', cvc_commit: '💾',
    cvc_branch: '🌿', cvc_restore: '⏮️', cvc_merge: '🔀', cvc_search: '🔍',
    cvc_diff: '📝', cvc_smart_search: '🧠',
  };
  return icons[name] || '🔧';
}

/** Simple HTML escaping. */
function escHtml(s) {
  const d = document.createElement('div');
  d.textContent = s || '';
  return d.innerHTML;
}

/**
 * @param {{ role: string; content: string }} msg
 * @param {boolean} [streaming=false]
 * @returns {HTMLElement}
 */
function appendChatMessage(msg, streaming = false) {
  const container = document.getElementById('chat-messages');
  const el = document.createElement('div');
  el.className = 'chat-message';

  const isUser = msg.role === 'user';
  el.innerHTML = `
    <div class="chat-avatar ${isUser ? 'user' : 'assistant'}">${isUser ? 'U' : 'C'}</div>
    <div class="chat-message-body">
      <div class="role">${isUser ? 'You' : 'CVC Agent'}</div>
      <div class="msg-content">${streaming ? '<span class="streaming-indicator"></span>' : ''}</div>
    </div>
  `;

  if (!streaming && msg.content) {
    const contentEl = el.querySelector('.msg-content');
    renderChatMarkdown(contentEl, msg.content);
  }

  container.appendChild(el);
  scrollChatToBottom();
  return el;
}

/**
 * @param {HTMLElement} el
 * @param {string} text
 */
function renderChatMarkdown(el, text) {
  try {
    if (typeof marked !== 'undefined') {
      el.innerHTML = marked.parse(text);
    } else {
      el.textContent = text;
    }
  } catch {
    el.textContent = text;
  }
}

function scrollChatToBottom() {
  const container = document.getElementById('chat-messages');
  container.scrollTop = container.scrollHeight;
}

function clearChat() {
  chatHistory = [];
  const container = document.getElementById('chat-messages');
  container.innerHTML = '';
}


// ── Tool Permission helpers ─────────────────────────

/**
 * Create an inline confirmation card for a tool about to execute.
 * Shows 5 CLI-style permission options.
 * @param {string} toolName
 * @param {object} args
 * @returns {HTMLElement}
 */
function createToolConfirmCard(toolName, args) {
  const card = document.createElement('div');
  card.className = 'tool-confirm-card';
  card.dataset.tool = toolName;

  const icon = getToolIcon(toolName);
  const argsPreview = Object.entries(args || {}).map(([k, v]) => `${k}: ${v}`).join(', ');

  card.innerHTML = `
    <div class="tool-confirm-header">
      <span class="tool-icon">${icon}</span>
      <span class="tool-confirm-label">Permission Required</span>
    </div>
    <div class="tool-confirm-body">
      <div class="tool-confirm-name"><strong>${escHtml(toolName)}</strong></div>
      <div class="tool-confirm-args"><pre>${escHtml(argsPreview).substring(0, 300)}</pre></div>
      <div class="tool-confirm-actions">
        <button class="btn btn-allow-once" data-decision="allow_once" title="Allow this one time only">Allow once</button>
        <button class="btn btn-allow-always" data-decision="allow_always" title="Always allow '${escHtml(toolName)}' this session">Always allow</button>
        <button class="btn btn-trust-all" data-decision="trust_all" title="Trust ALL tools for this session">Trust ALL</button>
        <button class="btn btn-deny" data-decision="deny" title="Deny this tool call">Deny</button>
        <button class="btn btn-deny-suggest" data-decision="deny_suggest" title="Deny and ask agent to suggest an alternative">Deny &amp; suggest</button>
      </div>
    </div>
  `;
  return card;
}

/**
 * Wait for the user to click one of the 5 permission options.
 * @param {HTMLElement} card
 * @returns {Promise<string>} one of: allow_once, allow_always, trust_all, deny, deny_suggest
 */
function waitForToolConfirmation(card) {
  return new Promise((resolve) => {
    const btns = card.querySelectorAll('.tool-confirm-actions button');
    btns.forEach(btn => {
      btn.addEventListener('click', () => {
        resolve(btn.dataset.decision);
      }, { once: true });
    });
  });
}

/** Decision labels for display */
const _DECISION_LABELS = {
  allow_once:    '✅ Allowed (once)',
  allow_always:  '✅ Always allowed',
  trust_all:     '✅ Trusted all',
  deny:          '❌ Denied',
  deny_suggest:  '❌ Denied (suggest alternative)',
  // Legacy compat
  allow:         '✅ Allowed',
};

/**
 * Update a confirm card to show the user's decision.
 * @param {HTMLElement} card
 * @param {string} decision
 */
function markConfirmCardDecision(card, decision) {
  const actions = card.querySelector('.tool-confirm-actions');
  if (actions) {
    const label = _DECISION_LABELS[decision] || decision;
    const cls = decision.startsWith('deny') ? 'deny' : 'allow';
    actions.innerHTML = `<span class="tool-confirm-decision ${cls}">${label}</span>`;
  }
}
