/**
 * Chat routes — /api/chat, /api/abort, /api/answer, /api/context
 */

// Summarize tool input for compact display
function summarize(name, input) {
  if (!input) return '';
  if (name === 'ReadFile' || name === 'WriteFile' || name === 'EditFile') return input.file_path || input.path || '';
  if (name === 'Bash') return (input.command || '').substring(0, 120);
  if (name === 'Grep') return `/${input.pattern}/ in ${input.path || '.'}`;
  if (name === 'Glob') return input.pattern || '';
  return JSON.stringify(input).substring(0, 100);
}

function summarizeDetail(name, input) {
  if (!input) return '';
  // Full input JSON for detail panel — only truncate huge content blobs
  try {
    const clone = { ...input };
    if (name === 'WriteFile' && clone.content && clone.content.length > 500) {
      clone.content = clone.content.substring(0, 500) + `... (${input.content.length} chars total)`;
    }
    if (name === 'EditFile') {
      if (clone.old_string && clone.old_string.length > 300) clone.old_string = clone.old_string.substring(0, 300) + '...';
      if (clone.new_string && clone.new_string.length > 300) clone.new_string = clone.new_string.substring(0, 300) + '...';
    }
    return JSON.stringify(clone, null, 2);
  } catch {
    return JSON.stringify(input).substring(0, 500);
  }
}

function summarizeResult(name, result) {
  if (typeof result === 'string') return result.substring(0, 300);
  return JSON.stringify(result).substring(0, 300);
}

export function setupChatRoutes(app, server) {
  // --- Chat SSE stream ---
  app.post('/api/chat', async (req, res) => {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    });

    const { message, images, mentions, selection } = req.body;
    const session = server.getSession(req);
    const abortController = new AbortController();
    session.abortController = abortController;

    const send = (event, data) => {
      if (!abortController.signal.aborted) res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
    };

    // Auto-name conversation
    if (!session.convName && message) {
      session.convName = String(message).substring(0, 20).replace(/\n/g, ' ') + (String(message).length > 20 ? '...' : '');
    }

    // Abort on client disconnect
    req.socket?.once('close', () => {
      if (!abortController.signal.aborted && !res.writableEnded) {
        abortController.abort();
      }
    });

    try {
      await session.orchestrator.processUserMessageStreaming(message, {
        onText: (text) => send('text', { text }),
        onThinking: (phase, text) => send('thinking', { phase, text }),
        onRetry: (attempt, delay, err) => send('retry', { attempt, delay: Math.round(delay), status: err.status || err.code }),
        onToolCall: (name, input) => send('tool_call', { name, input: summarize(name, input), detail: summarizeDetail(name, input) }),
        onToolResult: (name, result, diffData) => {
          const fullText = typeof result === 'string' ? result : JSON.stringify(result);
          const payload = { name, preview: summarizeResult(name, result), detail: fullText };
          if (diffData) payload.diff = diffData;
          send('tool_result', payload);
          if (name === 'VLComponentTest') {
            try {
              const parsed = JSON.parse(result);
              const screenshots = parsed.screenshots || [];
              if (!screenshots.length && parsed.screenshot) screenshots.push(parsed.screenshot);
              if (screenshots.length) send('screenshot', { tool: name, screenshots });
            } catch {}
          }
        },
        onTodo: (todos) => send('todo', { todos }),
        onAskUser: (q) => send('ask_user', q),
        onPlanMode: (data) => send('plan_mode', data),
        onDone: () => send('done', { msgCount: session.contextManager.getMessageCount() }),
        onError: (err) => send('error', { message: err }),
      }, { images, mentions, selection, signal: abortController.signal });
    } catch (e) {
      const eName = e.name || e.constructor?.name || '';
      const isAbort = eName === 'APIUserAbortError' || eName === 'AbortError' ||
        e.code === 'ERR_ABORTED' || (e.message || '').includes('aborted');
      if (!isAbort) send('error', { message: e.message });
    }

    session.abortController = null;
    const chatId = req.body?.chatId || '0';
    server.autosaveSession(chatId, session).catch(() => {}).finally(() => {
      // Update messageCount in convRegistry and broadcast for multi-window chat sync
      const msgCount = session.contextManager?.messages?.length || 0;
      const conv = server._convRegistry?.conversations?.find(c => String(c.id) === String(chatId));
      if (conv) conv.messageCount = msgCount;
      server.broadcast({ type: 'chat_state_changed', chatId: parseInt(chatId) || 0, messageCount: msgCount });
    });
    res.end();
  });

  // --- Abort ---
  app.post('/api/abort', async (req, res) => {
    const session = server.getSession(req);
    if (session.abortController) {
      session.abortController.abort();
      session.abortController = null;
    }
    // Abort active workflow
    if (server._activeExecutor) {
      server._activeExecutor.abort();
      server._activeExecutor = null;
    }
    res.json({ ok: true });
  });

  // --- Answer AskUser ---
  app.post('/api/answer', (req, res) => {
    const session = server.getSession(req);
    if (session.orchestrator?._pendingQuestion) {
      session.orchestrator.resolveUserAnswer(req.body.answer || req.body);
      res.json({ ok: true });
    } else {
      res.json({ ok: false, error: 'No pending question' });
    }
  });

  // --- Context ---
  app.get('/api/context', (req, res) => {
    const { contextManager } = server.getSession(req);
    res.json(contextManager.getUsage());
  });

  app.post('/api/context/clear', (req, res) => {
    const { contextManager, orchestrator } = server.getSession(req);
    contextManager.messages = [];
    contextManager.turnCount = 0;
    contextManager.excludedIndices.clear();
    contextManager.estimateTokens();
    orchestrator.isFirstMessage = true;
    orchestrator.todos = [];
    res.json({ ok: true });
  });

  app.post('/api/context/toggle-exclude', (req, res) => {
    const { startIdx, endIdx } = req.body;
    const { contextManager } = server.getSession(req);
    if (startIdx == null) return res.status(400).json({ error: 'startIdx required' });
    const end = endIdx ?? startIdx;
    for (let i = startIdx; i <= end; i++) {
      if (contextManager.excludedIndices.has(i)) contextManager.excludedIndices.delete(i);
      else contextManager.excludedIndices.add(i);
    }
    contextManager.estimateTokens();
    res.json({ ok: true, excluded: [...contextManager.excludedIndices] });
  });

  app.get('/api/context/messages', (req, res) => {
    const { contextManager } = server.getSession(req);
    res.json({
      messages: contextManager.messages.map((m, i) => ({
        role: m.role, idx: i,
        preview: typeof m.content === 'string' ? m.content.substring(0, 200) : '[complex]',
        excluded: contextManager.excludedIndices.has(i),
      })),
    });
  });
}
