/**
 * TOML utilities for MCP agent configuration.
 *
 * Used by agents whose config format is 'toml' (currently: Codex).
 * Mirrors the TypeScript implementation in:
 *   packages/web/app/api/mcp/install/route.ts  (buildTomlEntry, mergeTomlEntry)
 *
 * No external TOML library — hand-rolled for the narrow MCP config use case.
 *
 * @module toml
 */

function tomlString(value) {
  return JSON.stringify(String(value));
}

function tomlKey(key) {
  const value = String(key);
  return /^[A-Za-z0-9_-]+$/.test(value) ? value : tomlString(value);
}

function tomlTablePath(sectionKey, serverName, ...suffixes) {
  return [
    ...String(sectionKey).split('.').filter(Boolean).map(tomlKey),
    tomlKey(serverName),
    ...suffixes.map(tomlKey),
  ].join('.');
}

/**
 * Generate a TOML section string for an MCP server entry.
 *
 * @param {string} sectionKey  Top-level table name, e.g. 'mcp_servers'
 * @param {string} serverName  Server name, e.g. 'mindos'
 * @param {Record<string, unknown>} entry  MCP entry object
 * @returns {string} TOML block (without trailing newline)
 *
 * @example
 *   buildTomlEntry('mcp_servers', 'mindos', {
 *     type: 'stdio', command: 'mindos', args: ['mcp'],
 *     env: { MCP_TRANSPORT: 'stdio' },
 *   })
 *   // →
 *   // [mcp_servers.mindos]
 *   // type = "stdio"
 *   // command = "mindos"
 *   // args = ["mcp"]
 *   //
 *   // [mcp_servers.mindos.env]
 *   // MCP_TRANSPORT = "stdio"
 */
export function buildTomlEntry(sectionKey, serverName, entry) {
  const lines = [];

  // Main section header
  lines.push(`[${tomlTablePath(sectionKey, serverName)}]`);

  // Scalar + array fields (order matches TS version)
  if (entry.type != null)    lines.push(`type = ${tomlString(entry.type)}`);
  if (entry.command != null) lines.push(`command = ${tomlString(entry.command)}`);
  if (entry.url != null)     lines.push(`url = ${tomlString(entry.url)}`);
  if (Array.isArray(entry.args)) {
    lines.push(`args = [${entry.args.map(tomlString).join(', ')}]`);
  }

  // Nested [section.server.env] sub-table
  if (entry.env && typeof entry.env === 'object') {
    lines.push('');
    lines.push(`[${tomlTablePath(sectionKey, serverName, 'env')}]`);
    for (const [k, v] of Object.entries(entry.env)) {
      lines.push(`${tomlKey(k)} = ${tomlString(v)}`);
    }
  }

  // Nested [section.server.headers] sub-table
  if (entry.headers && typeof entry.headers === 'object') {
    lines.push('');
    lines.push(`[${tomlTablePath(sectionKey, serverName, 'headers')}]`);
    for (const [k, v] of Object.entries(entry.headers)) {
      lines.push(`${tomlKey(k)} = ${tomlString(v)}`);
    }
  }

  return lines.join('\n');
}

/**
 * Replace or append a [section.server] block in existing TOML content.
 *
 * Algorithm:
 *   1. Walk existing lines; skip lines belonging to the target section
 *      (main header, .env sub-header, .headers sub-header).
 *   2. Strip trailing blank lines.
 *   3. Append the new block generated by buildTomlEntry().
 *
 * @param {string} existing     Current file content (may be empty)
 * @param {string} sectionKey   Top-level table name, e.g. 'mcp_servers'
 * @param {string} serverName   Server name, e.g. 'mindos'
 * @param {Record<string, unknown>} entry  MCP entry object
 * @returns {string} Merged TOML content
 */
export function mergeTomlEntry(existing, sectionKey, serverName, entry) {
  const sectionHeader  = `[${tomlTablePath(sectionKey, serverName)}]`;
  const envHeader      = `[${tomlTablePath(sectionKey, serverName, 'env')}]`;
  const headersHeader  = `[${tomlTablePath(sectionKey, serverName, 'headers')}]`;
  const legacyHeaders = new Set([
    `[${sectionKey}.${serverName}]`,
    `[${sectionKey}.${serverName}.env]`,
    `[${sectionKey}.${serverName}.headers]`,
  ]);
  const newBlock       = buildTomlEntry(sectionKey, serverName, entry);

  const lines  = existing.split('\n');
  const result = [];
  let skipping = false;

  for (const line of lines) {
    const trimmed = line.trim();

    // Entering one of the target sections → start skipping
    if (trimmed === sectionHeader || trimmed === envHeader || trimmed === headersHeader || legacyHeaders.has(trimmed)) {
      skipping = true;
      continue;
    }

    // A new [section] header that is NOT ours → stop skipping
    if (skipping && trimmed.startsWith('[')) {
      skipping = false;
    }

    if (!skipping) {
      result.push(line);
    }
  }

  // Remove trailing blank lines before appending
  while (result.length > 0 && result[result.length - 1].trim() === '') {
    result.pop();
  }

  // Append new block with surrounding blank lines
  result.push('');
  result.push(newBlock);
  result.push('');

  return result.join('\n');
}
