const fs = require('fs');
const path = require('path');

/**
 * Phase 7E: Diagram Generator
 * Auto-generates Mermaid diagrams from graph analysis outputs.
 */

/**
 * Generate a subsystem dependency diagram from the dependency matrix.
 * @param {object} subsystemMap - Result from buildSubsystems
 * @returns {string} Mermaid graph TD source
 */
function generateDependencyDiagram(subsystemMap) {
  const lines = ['graph TD'];
  const { subsystems, crossCutting, dependencyMatrix } = subsystemMap;

  // Define nodes
  for (const sub of subsystems) {
    const label = sub.name.charAt(0).toUpperCase() + sub.name.slice(1);
    if (sub.kind === 'cross-cutting') {
      lines.push(`  ${sub.name}["${label} (shared)"]:::shared`);
    } else {
      lines.push(`  ${sub.name}["${label}"]`);
    }
  }

  // Define edges (skip cross-cutting → cross-cutting to reduce noise)
  for (const [key, val] of Object.entries(dependencyMatrix)) {
    const [from, to] = key.split('→');
    const weight = val.calls + val.imports;
    if (weight === 0) continue;

    // Skip edges between two cross-cutting subsystems
    if (crossCutting.includes(from) && crossCutting.includes(to)) continue;

    const label = weight > 5 ? `|${weight}|` : '';
    lines.push(`  ${from} -->${label} ${to}`);
  }

  // Style
  lines.push('  classDef shared fill:#f9f,stroke:#333,stroke-dasharray: 5 5');

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

/**
 * Generate a sequence diagram from a flow trace.
 * @param {object} flowResult - Result from traceFlow
 * @returns {string} Mermaid sequenceDiagram source
 */
function generateFlowDiagram(flowResult) {
  const lines = ['sequenceDiagram'];

  // Participants in order
  for (const sub of flowResult.subsystemSequence) {
    const label = sub.charAt(0).toUpperCase() + sub.slice(1);
    lines.push(`  participant ${sub} as ${label}`);
  }

  // Messages from flow steps
  let prevSub = null;
  for (const step of flowResult.flow) {
    if (step.crossedVia && prevSub && prevSub !== step.subsystem) {
      const funcName = step.entity.includes(':') ? step.entity.split(':')[1] : step.entity.split('/').pop();
      lines.push(`  ${prevSub}->>${step.subsystem}: ${funcName}()`);
    }
    prevSub = step.subsystem;
  }

  // Note cycles
  for (const cycle of flowResult.cyclesDetected) {
    const sub = null; // We'd need subsystem lookup, just note it
    const atFunc = cycle.at.includes(':') ? cycle.at.split(':')[1] : cycle.at;
    const backFunc = cycle.backEdgeTo.includes(':') ? cycle.backEdgeTo.split(':')[1] : cycle.backEdgeTo;
    lines.push(`  Note right of ${flowResult.subsystemSequence[flowResult.subsystemSequence.length - 1]}: Cycle: ${atFunc} ↔ ${backFunc}`);
  }

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

/**
 * Generate a contract/class diagram from extracted contracts.
 * @param {Array} contracts - Array of contract objects with fields
 * @returns {string} Mermaid classDiagram source
 */
function generateContractDiagram(contracts) {
  const lines = ['classDiagram'];

  for (const c of contracts) {
    // Sanitize name for Mermaid (no spaces, parens, special chars)
    const safeName = c.name.replace(/[^a-zA-Z0-9_]/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '');
    if (!safeName) continue;

    if (c.type === 'Interface' || c.type === 'TypeAlias') {
      lines.push(`  class ${safeName} {`);
      if (c.fields) {
        for (const f of c.fields) {
          lines.push(`    +${f.name}: ${f.type}`);
        }
      }
      lines.push('  }');
      lines.push(`  <<${c.type}>> ${safeName}`);

      if (c.extends) {
        for (const ext of c.extends) {
          const safeExt = ext.replace(/[^a-zA-Z0-9_]/g, '_');
          lines.push(`  ${safeExt} <|-- ${safeName}`);
        }
      }
    } else if (c.type === 'Enum') {
      lines.push(`  class ${safeName} {`);
      lines.push('    <<enumeration>>');
      if (c.members) {
        for (const m of c.members) {
          lines.push(`    ${m}`);
        }
      }
      lines.push('  }');
    } else if (c.type === 'HelmValues' || c.type === 'HelmServices' || c.type === 'HelmWorkloads' || c.type === 'HelmDependencies') {
      lines.push(`  class ${safeName} {`);
      lines.push(`    <<${c.type}>>`);
      if (c.fields) {
        for (const f of c.fields) {
          const safeField = f.name.replace(/[^a-zA-Z0-9_:.-]/g, '_');
          const safeType = (f.type || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '_');
          lines.push(`    +${safeField}: ${safeType}`);
        }
      }
      lines.push('  }');
    }
  }

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

if (require.main === module) {
  const cmd = process.argv[2];
  const inputPath = process.argv[3];

  if (!cmd || !inputPath) {
    console.error('Usage: node diagrams.js <deps|flow|contracts> <input.json>');
    process.exit(1);
  }

  const data = JSON.parse(fs.readFileSync(inputPath, 'utf8'));

  if (cmd === 'deps') {
    console.log(generateDependencyDiagram(data));
  } else if (cmd === 'flow') {
    console.log(generateFlowDiagram(data));
  } else if (cmd === 'contracts') {
    console.log(generateContractDiagram(data.contracts || data));
  } else {
    console.error('Unknown command:', cmd);
    process.exit(1);
  }
}

module.exports = { generateDependencyDiagram, generateFlowDiagram, generateContractDiagram };
