'use strict';

/**
 * status-formatter.js — Pure function: SessionState -> formatted Mattermost text.
 *
 * Output format:
 *   [ACTIVE] main | 38s
 *   Reading live-status source code...
 *     exec: ls /agents/sessions [OK]
 *   Analyzing agent configurations...
 *     Sub-agent: proj035-planner
 *       Reading protocol...
 *       [DONE] 28s
 *   [DONE] 53s | 12.4k tokens
 */

const MAX_STATUS_LINES = parseInt(process.env.MAX_STATUS_LINES, 10) || 20;
const MAX_LINE_CHARS = 120;

/**
 * Format a SessionState into a Mattermost text string.
 *
 * @param {object} sessionState
 * @param {string} sessionState.sessionKey
 * @param {string} sessionState.status - 'active' | 'done' | 'error' | 'interrupted'
 * @param {number} sessionState.startTime - ms since epoch
 * @param {Array<string>} sessionState.lines - Status lines (most recent activity)
 * @param {Array<object>} [sessionState.children] - Child session states
 * @param {number} [sessionState.tokenCount] - Token count if available
 * @param {string} [sessionState.agentId] - Agent ID (e.g. "main")
 * @param {number} [sessionState.depth] - Nesting depth (0 = top-level)
 * @returns {string}
 */
function format(sessionState, opts = {}) {
  const maxLines = opts.maxLines || MAX_STATUS_LINES;
  const depth = sessionState.depth || 0;
  const indent = '  '.repeat(depth);

  const lines = [];

  // Header line
  const elapsed = formatElapsed(Date.now() - sessionState.startTime);
  const agentId = sessionState.agentId || extractAgentId(sessionState.sessionKey);
  const statusPrefix = statusIcon(sessionState.status);
  lines.push(`${indent}**${statusPrefix}** \`${agentId}\` | ${elapsed}`);

  // Status lines (trimmed to maxLines, most recent)
  const statusLines = (sessionState.lines || []).slice(-maxLines);
  for (const line of statusLines) {
    lines.push(`${indent}${formatStatusLine(truncateLine(line))}`);
  }

  // Child sessions (sub-agents)
  if (sessionState.children && sessionState.children.length > 0) {
    for (const child of sessionState.children) {
      const childLines = format(child, { maxLines: Math.floor(maxLines / 2), ...opts }).split('\n');
      lines.push(...childLines);
    }
  }

  // Footer line (only for done/error/interrupted)
  if (sessionState.status !== 'active') {
    const tokenStr = sessionState.tokenCount
      ? ` | ${formatTokens(sessionState.tokenCount)} tokens`
      : '';
    lines.push(`${indent}**[${sessionState.status.toUpperCase()}]** ${elapsed}${tokenStr}`);
  }

  // Wrap in blockquote at top level — visually distinct (left border),
  // never collapses like code blocks do, supports inline markdown
  var body = lines.join('\n');
  if (depth === 0) {
    body = body
      .split('\n')
      .map(function (l) {
        return '> ' + l;
      })
      .join('\n');
  }
  return body;
}

/**
 * Format elapsed milliseconds as human-readable string.
 * @param {number} ms
 * @returns {string}
 */
function formatElapsed(ms) {
  if (ms < 0) ms = 0;
  const s = Math.floor(ms / 1000);
  const m = Math.floor(s / 60);
  const h = Math.floor(m / 60);
  if (h > 0) return `${h}h${m % 60}m`;
  if (m > 0) return `${m}m${s % 60}s`;
  return `${s}s`;
}

/**
 * Format token count as compact string (e.g. 12400 -> "12.4k").
 * @param {number} count
 * @returns {string}
 */
function formatTokens(count) {
  if (count >= 1000000) return `${(count / 1000000).toFixed(1)}M`;
  if (count >= 1000) return `${(count / 1000).toFixed(1)}k`;
  return String(count);
}

/**
 * Get status icon prefix.
 * @param {string} status
 * @returns {string}
 */
function statusIcon(status) {
  switch (status) {
    case 'active':
      return '[ACTIVE]';
    case 'done':
      return '[DONE]';
    case 'error':
      return '[ERROR]';
    case 'interrupted':
      return '[INTERRUPTED]';
    default:
      return '[UNKNOWN]';
  }
}

/**
 * Format a status line with inline markdown.
 * Tool calls get inline code formatting; thinking text stays plain.
 * @param {string} line
 * @returns {string}
 */
function formatStatusLine(line) {
  // Tool call lines: "toolName: arguments [OK]" or "toolName: label"
  var match = line.match(/^(\S+?): (.+?)( \[OK\]| \[ERR\])?$/);
  if (match) {
    var marker = match[3] || '';
    return '`' + match[1] + ':` ' + match[2] + marker;
  }
  // Thinking text — use a unicode marker to distinguish from tool calls
  // Avoid markdown italic (*) since it breaks with special characters
  return '\u2502 ' + line;
}

/**
 * Truncate a line to MAX_LINE_CHARS.
 * @param {string} line
 * @returns {string}
 */
function truncateLine(line) {
  if (line.length <= MAX_LINE_CHARS) return line;
  return line.slice(0, MAX_LINE_CHARS - 3) + '...';
}

/**
 * Extract agent ID from session key.
 * Session key format: "agent:main:mattermost:channel:abc123:thread:xyz"
 * @param {string} sessionKey
 * @returns {string}
 */
function extractAgentId(sessionKey) {
  if (!sessionKey) return 'unknown';
  const parts = sessionKey.split(':');
  // "agent:main:..." -> "main"
  if (parts[0] === 'agent' && parts[1]) return parts[1];
  return sessionKey.split(':')[0] || 'unknown';
}

module.exports = { format, formatElapsed, formatTokens, statusIcon, truncateLine, extractAgentId };
