import fs from 'fs/promises';
import os from 'os';
import path from 'path';

const repoRoot = '/Users/ivx/Documents/VLCode-Lite';
const examplesDir = path.join(repoRoot, 'examples', 'workflows');
const emptyWindowWorkflowDir = path.join(os.homedir(), '.vl-code', 'empty-window', '.vl-code', 'workflows');

const solverSource = `import fs from 'fs';

const cavePath = process.argv[2] || 'cave.json';
const cave = JSON.parse(fs.readFileSync(cavePath, 'utf8'));
const trace = [];
const seen = new Map();
let best = null;

function scoreState(node, energy, crystals, path) {
  return (node === cave.goal ? 500 : 0) + (crystals * 11) + energy - path.length;
}

function remember(signature, score) {
  const prev = seen.get(signature) ?? -Infinity;
  if (prev >= score) return false;
  seen.set(signature, score);
  return true;
}

function explore(node, energy, crystals, path, visitedRooms) {
  const room = cave.rooms[node] || {};
  const nextVisitedRooms = new Set(visitedRooms);
  const gained = nextVisitedRooms.has(node) ? 0 : (room.crystals || 0);
  nextVisitedRooms.add(node);
  const nextCrystals = crystals + gained;
  const nextPath = [...path, node];
  const signature = [node, energy, nextCrystals, [...nextVisitedRooms].sort().join(',')].join('|');
  const score = scoreState(node, energy, nextCrystals, nextPath);
  if (!remember(signature, score)) return;

  trace.push(\`visit=\${node}; energy=\${energy}; crystals=\${nextCrystals}; path=\${nextPath.join('>')}\`);
  if (!best || score > best.score) {
    best = { node, energy, crystals: nextCrystals, path: nextPath, score };
  }
  if (node === cave.goal) return;

  const edges = (cave.tunnels[node] || []).slice().sort((a, b) => {
    const aReward = (cave.rooms[a.to]?.crystals || 0) - a.cost;
    const bReward = (cave.rooms[b.to]?.crystals || 0) - b.cost;
    return bReward - aReward;
  });

  for (const edge of edges) {
    if (energy < edge.cost) {
      trace.push(\`skip=\${node}->\${edge.to}; reason=energy; need=\${edge.cost}; have=\${energy}\`);
      continue;
    }
    const recharge = cave.rooms[edge.to]?.recharge || 0;
    explore(edge.to, energy - edge.cost + recharge, nextCrystals, nextPath, nextVisitedRooms);
  }
}

explore(cave.start, cave.energy, 0, [], new Set());

const reportLines = [
  \`zone=\${cave.zone}\`,
  \`goal=\${cave.goal}\`,
  \`bestNode=\${best?.node || 'unknown'}\`,
  \`score=\${best?.score ?? 0}\`,
  \`energyLeft=\${best?.energy ?? 0}\`,
  \`crystals=\${best?.crystals ?? 0}\`,
  \`route=\${best?.path?.join('>') || ''}\`
];

fs.writeFileSync('report.txt', reportLines.join('\\n'));
fs.writeFileSync('trace.txt', trace.join('\\n'));
console.log(\`best=\${best?.node || 'unknown'}; score=\${best?.score ?? 0}; route=\${best?.path?.join('>') || ''}; crystals=\${best?.crystals ?? 0}\`);
`;

function makeScoutWorkflow(name = 'CaveZoneScout') {
  return {
    version: '3.16',
    name,
    description: 'Writes a cave-search program into an isolated child space, runs it, and captures the trace/report.',
    steps: [
      {
        id: 'Tool_010_WriteMap',
        tool: 'WriteFile',
        input: {
          file_path: '="cave.json"',
          content: '=mapJson',
        },
        next: 'Tool_020_WriteSolver',
      },
      {
        id: 'Tool_020_WriteSolver',
        tool: 'WriteFile',
        input: {
          file_path: '="explore-cave.mjs"',
          content: solverSource,
        },
        next: 'Tool_030_RunSolver',
      },
      {
        id: 'Tool_030_RunSolver',
        tool: 'Bash',
        input: {
          command: '="node explore-cave.mjs cave.json"',
        },
        out: {
          '$solverStdout': '=_result',
        },
        next: 'Tool_040_ReadReport',
      },
      {
        id: 'Tool_040_ReadReport',
        tool: 'ReadFile',
        input: {
          file_path: '="report.txt"',
        },
        out: {
          '$reportText': '=_result',
        },
        next: 'Tool_050_ReadTrace',
      },
      {
        id: 'Tool_050_ReadTrace',
        tool: 'ReadFile',
        input: {
          file_path: '="trace.txt"',
          limit: 80,
        },
        out: {
          '$traceText': '=_result',
        },
        next: 'Set_060_Summary',
      },
      {
        id: 'Set_060_Summary',
        target: '$zoneSummary',
        value: '=zoneName + " => " + $solverStdout',
        next: 'Write_070_Summary',
      },
      {
        id: 'Write_070_Summary',
        target: '="Artifacts/zone-summary.txt"',
        value: '=$zoneSummary',
        mode: 'overwrite',
        next: 'Stop_End',
      },
      { id: 'Stop_End' },
    ],
  };
}

const northMap = {
  zone: 'North Rim',
  start: 'N0',
  goal: 'N7',
  energy: 10,
  rooms: {
    N0: { crystals: 0 },
    N1: { crystals: 2 },
    N2: { crystals: 1, recharge: 1 },
    N3: { crystals: 3 },
    N4: { crystals: 2 },
    N5: { crystals: 4, recharge: 2 },
    N6: { crystals: 1 },
    N7: { crystals: 6 },
  },
  tunnels: {
    N0: [{ to: 'N1', cost: 2 }, { to: 'N2', cost: 3 }],
    N1: [{ to: 'N3', cost: 2 }, { to: 'N4', cost: 3 }],
    N2: [{ to: 'N4', cost: 2 }, { to: 'N5', cost: 4 }],
    N3: [{ to: 'N6', cost: 2 }],
    N4: [{ to: 'N6', cost: 1 }, { to: 'N5', cost: 2 }],
    N5: [{ to: 'N7', cost: 2 }],
    N6: [{ to: 'N7', cost: 1 }],
  },
};

const southMap = {
  zone: 'South Spiral',
  start: 'S0',
  goal: 'S8',
  energy: 11,
  rooms: {
    S0: { crystals: 0 },
    S1: { crystals: 1 },
    S2: { crystals: 3 },
    S3: { crystals: 2, recharge: 1 },
    S4: { crystals: 4 },
    S5: { crystals: 1 },
    S6: { crystals: 5, recharge: 2 },
    S7: { crystals: 2 },
    S8: { crystals: 7 },
  },
  tunnels: {
    S0: [{ to: 'S1', cost: 1 }, { to: 'S2', cost: 3 }],
    S1: [{ to: 'S3', cost: 2 }, { to: 'S4', cost: 4 }],
    S2: [{ to: 'S4', cost: 2 }, { to: 'S5', cost: 3 }],
    S3: [{ to: 'S6', cost: 2 }],
    S4: [{ to: 'S6', cost: 1 }, { to: 'S7', cost: 2 }],
    S5: [{ to: 'S7', cost: 2 }],
    S6: [{ to: 'S8', cost: 2 }],
    S7: [{ to: 'S8', cost: 1 }],
  },
};

const anomalyMap = {
  zone: 'Deep Anomaly',
  start: 'D0',
  goal: 'D9',
  energy: 14,
  rooms: {
    D0: { crystals: 0 },
    D1: { crystals: 2 },
    D2: { crystals: 3 },
    D3: { crystals: 1, recharge: 1 },
    D4: { crystals: 4 },
    D5: { crystals: 2, recharge: 2 },
    D6: { crystals: 6 },
    D7: { crystals: 3 },
    D8: { crystals: 5 },
    D9: { crystals: 9 },
  },
  tunnels: {
    D0: [{ to: 'D1', cost: 2 }, { to: 'D2', cost: 2 }],
    D1: [{ to: 'D3', cost: 2 }, { to: 'D4', cost: 4 }],
    D2: [{ to: 'D4', cost: 2 }, { to: 'D5', cost: 3 }],
    D3: [{ to: 'D6', cost: 3 }],
    D4: [{ to: 'D6', cost: 2 }, { to: 'D7', cost: 2 }],
    D5: [{ to: 'D7', cost: 1 }, { to: 'D8', cost: 3 }],
    D6: [{ to: 'D9', cost: 2 }],
    D7: [{ to: 'D9', cost: 2 }],
    D8: [{ to: 'D9', cost: 1 }],
  },
};

const scoutWorkflow = makeScoutWorkflow('CaveZoneScout');
const deepScoutWorkflow = makeScoutWorkflow('GeneratedDeepScout');

const supervisorWorkflow = {
  version: '3.16',
  name: 'CaveSupervisorDemo',
  description: 'Supervisor workflow that runs two scout subflows in parallel, pauses for review, then generates a deep-scout child workflow and resumes exploration.',
  steps: [
    {
      id: 'Set_010_OutputRoot',
      target: '$outputRoot',
      value: '=".codex/demo-artifacts/cave-workflow-demo"',
      next: 'Set_020_DeepFlowFile',
    },
    {
      id: 'Set_020_DeepFlowFile',
      target: '$deepFlowFile',
      value: '=".vl-code/workflows/cave-deep-scout-generated.json"',
      next: 'Fork_030_InitialScouts',
    },
    {
      id: 'Fork_030_InitialScouts',
      children: ['Subflow_040_NorthScout', 'Subflow_050_SouthScout'],
      next: 'Pause_060_ManagerReview',
    },
    {
      id: 'Subflow_040_NorthScout',
      workflow_path: 'cave-zone-scout',
      mode: 'sync',
      work_dir: '=$outputRoot + "/north"',
      params: {
        zoneName: '="north-rim"',
        mapJson: JSON.stringify(northMap, null, 2),
      },
      out: {
        '$northSummary': '=_result.variables["$zoneSummary"]',
        '$northReport': '=_result.variables["$reportText"]',
      },
    },
    {
      id: 'Subflow_050_SouthScout',
      workflow_path: 'cave-zone-scout',
      mode: 'sync',
      work_dir: '=$outputRoot + "/south"',
      params: {
        zoneName: '="south-spiral"',
        mapJson: JSON.stringify(southMap, null, 2),
      },
      out: {
        '$southSummary': '=_result.variables["$zoneSummary"]',
        '$southReport': '=_result.variables["$reportText"]',
      },
    },
    {
      id: 'Pause_060_ManagerReview',
      reason: 'Manager review: compare north/south scout reports before dispatching a deep anomaly probe.',
      next: 'Tool_070_WriteDeepScoutWorkflow',
    },
    {
      id: 'Tool_070_WriteDeepScoutWorkflow',
      tool: 'WriteFile',
      input: {
        file_path: '=$deepFlowFile',
        content: JSON.stringify(deepScoutWorkflow, null, 2),
      },
      next: 'Subflow_080_DeepScout',
    },
    {
      id: 'Subflow_080_DeepScout',
      workflow_path: 'cave-deep-scout-generated',
      mode: 'sync',
      work_dir: '=$outputRoot + "/deep-scout"',
      params: {
        zoneName: '="deep-anomaly"',
        mapJson: JSON.stringify(anomalyMap, null, 2),
      },
      out: {
        '$deepSummary': '=_result.variables["$zoneSummary"]',
        '$deepReport': '=_result.variables["$reportText"]',
      },
      next: 'Set_090_FinalNarrative',
    },
    {
      id: 'Set_090_FinalNarrative',
      target: '$finalNarrative',
      value: '="North\\n" + $northSummary + "\\n\\nSouth\\n" + $southSummary + "\\n\\nDeep\\n" + $deepSummary',
      next: 'Write_100_ManagerReport',
    },
    {
      id: 'Write_100_ManagerReport',
      target: '=$outputRoot + "/manager-report.txt"',
      value: '=$finalNarrative',
      mode: 'overwrite',
      next: 'Stop_End',
    },
    { id: 'Stop_End' },
  ],
};

async function writeWorkflow(targetDir, fileName, workflow) {
  await fs.mkdir(targetDir, { recursive: true });
  await fs.writeFile(path.join(targetDir, fileName), JSON.stringify(workflow, null, 2), 'utf8');
}

await writeWorkflow(examplesDir, 'cave-zone-scout.json', scoutWorkflow);
await writeWorkflow(examplesDir, 'cave-supervisor-demo.json', supervisorWorkflow);
await writeWorkflow(emptyWindowWorkflowDir, 'cave-zone-scout.json', scoutWorkflow);
await writeWorkflow(emptyWindowWorkflowDir, 'cave-supervisor-demo.json', supervisorWorkflow);

console.log(JSON.stringify({
  ok: true,
  examplesDir,
  emptyWindowWorkflowDir,
  files: ['cave-zone-scout.json', 'cave-supervisor-demo.json'],
}, null, 2));
