import db from '../db.js';

export function generateSurgeConfig(hostUrl: string): string {
  // Get first enabled subscription's raw_config as base template
  const sub = db.prepare(
    'SELECT raw_config FROM subscriptions WHERE enabled = 1 AND raw_config IS NOT NULL ORDER BY id LIMIT 1'
  ).get() as any;

  if (!sub?.raw_config) {
    return '# No subscription config available. Add and fetch a subscription first.';
  }

  // Collect enabled fetched nodes
  const fetchedNodes = db.prepare(
    'SELECT surge_line FROM fetched_nodes WHERE enabled = 1 ORDER BY subscription_id, id'
  ).all() as any[];

  // Collect enabled static nodes (these go FIRST)
  const staticNodes = db.prepare(
    'SELECT surge_line FROM static_nodes WHERE enabled = 1 ORDER BY sort_order, id'
  ).all() as any[];

  // Collect enabled rules
  const userRules = db.prepare(
    'SELECT type, value, action, comment FROM rules WHERE enabled = 1 ORDER BY sort_order, id'
  ).all() as any[];

  // Static nodes first, then fetched nodes
  const staticLines = staticNodes.map((n: any) => n.surge_line);
  const fetchedLines = fetchedNodes.map((n: any) => n.surge_line);
  const allNodeLines = [...staticLines, ...fetchedLines];
  const allNodeNames = allNodeLines.map((l: string) => l.split(' = ')[0].trim());

  // Build rule lines
  const ruleLines = userRules.map((r: any) => {
    const line = `${r.type},${r.value},${r.action}`;
    return r.comment ? `${line} // ${r.comment}` : line;
  });

  let config = sub.raw_config;

  // Replace [Proxy] section with only enabled nodes
  config = rebuildProxySection(config, staticLines, fetchedLines);

  // Rebuild [Proxy Group] select groups with only enabled node names
  config = rebuildProxyGroup(config, allNodeNames);

  // Inject user rules at the beginning of [Rule] section
  if (ruleLines.length > 0) {
    config = injectRules(config, ruleLines);
  }

  // Rewrite MANAGED-CONFIG URL
  config = config.replace(
    /^#!MANAGED-CONFIG\s+\S+/m,
    `#!MANAGED-CONFIG ${hostUrl}`
  );

  return config;
}

/**
 * Replace the entire [Proxy] section content with only enabled nodes.
 * Static nodes go first, then fetched nodes.
 */
function rebuildProxySection(config: string, staticLines: string[], fetchedLines: string[]): string {
  const lines = config.split('\n');
  const result: string[] = [];
  let inProxySection = false;
  let proxyHeaderEmitted = false;

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

    if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
      if (inProxySection && !proxyHeaderEmitted) {
        // Emit our rebuilt proxy content before leaving the section
        emitProxyContent(result, staticLines, fetchedLines);
        proxyHeaderEmitted = true;
      }
      inProxySection = trimmed === '[Proxy]';
      result.push(line);
      if (inProxySection) {
        // Emit all enabled nodes right after [Proxy] header
        emitProxyContent(result, staticLines, fetchedLines);
        proxyHeaderEmitted = true;
      }
      continue;
    }

    if (inProxySection) {
      // Skip original proxy lines (we replaced them)
      continue;
    }

    result.push(line);
  }

  // If [Proxy] was the last section
  if (inProxySection && !proxyHeaderEmitted) {
    emitProxyContent(result, staticLines, fetchedLines);
  }

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

function emitProxyContent(result: string[], staticLines: string[], fetchedLines: string[]) {
  if (staticLines.length > 0) {
    result.push('# --- 自定义节点 ---');
    staticLines.forEach(l => result.push(l));
    result.push('');
  }
  if (fetchedLines.length > 0) {
    result.push('# --- 订阅节点 ---');
    fetchedLines.forEach(l => result.push(l));
    result.push('');
  }
}

/**
 * Rebuild [Proxy Group] select groups to contain only the enabled node names.
 */
function rebuildProxyGroup(config: string, allNodeNames: string[]): string {
  if (allNodeNames.length === 0) return config;

  const lines = config.split('\n');
  const result: string[] = [];
  let inProxyGroupSection = false;
  let handled = false;

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

    if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
      inProxyGroupSection = trimmed === '[Proxy Group]';
    }

    if (inProxyGroupSection && !handled && trimmed.includes('= select,')) {
      // Rebuild: keep group name and "= select," prefix, replace node list
      const eqSelect = trimmed.indexOf('= select,');
      const prefix = trimmed.slice(0, eqSelect + '= select,'.length);
      result.push(prefix + ' ' + allNodeNames.join(', '));
      handled = true;
      continue;
    }

    result.push(line);
  }

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

function injectRules(config: string, ruleLines: string[]): string {
  const lines = config.split('\n');
  const result: string[] = [];

  for (const line of lines) {
    result.push(line);
    if (line.trim() === '[Rule]') {
      result.push('# --- 自定义规则 ---');
      ruleLines.forEach(r => result.push(r));
      result.push('');
    }
  }

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