/**
 * Concise root CLAUDE.md generator. Doorway, not warehouse. Heavy detail
 * lives elsewhere: session-notes/, rules/, hooks/.
 *
 * Ported from AgentLens (`src/optimal-files/root-claude-md.js`). Pure.
 */

import path from 'node:path';

export const MAX_LINES_HARD = 200;
export const TARGET_LINES_MAX = 150;

export function generateRootClaudeMd(analysis) {
  const a = analysis;
  const slug = (a.project && (a.project.slug || a.project.cwd || 'project')) || 'project';
  const projectName = (a.project && (a.project.slug || path.basename(a.project.cwd || ''))) || 'project';
  const pkg = a.projectMeta && a.projectMeta.packageJson;
  const scripts = (a.projectMeta && a.projectMeta.scripts) || {};
  const runtime = (a.projectMeta && a.projectMeta.runtime) || (a.projectMeta && a.projectMeta.pyproject ? 'python' : null);

  const lines = [];
  lines.push(`# CLAUDE.md`);
  lines.push('');

  lines.push(`## Project`);
  const purpose = pkg && pkg.description
    ? pkg.description
    : `${projectName} — purpose not declared in package metadata. Edit this section by hand.`;
  lines.push(purpose);
  lines.push('');

  lines.push(`## Fast start`);
  const fast = [];
  if (runtime === 'node') {
    fast.push(`- Install: \`npm install\``);
    if (scripts.start) fast.push(`- Run:     \`npm start\``);
    else if (scripts.dev) fast.push(`- Run:     \`npm run dev\``);
    if (scripts.test) fast.push(`- Test:    \`npm test\``);
    if (scripts.lint) fast.push(`- Lint:    \`npm run lint\``);
    if (scripts.build) fast.push(`- Build:   \`npm run build\``);
    if (scripts.typecheck) fast.push(`- Types:   \`npm run typecheck\``);
  } else if (runtime === 'python') {
    fast.push(`- Install: \`pip install -e .\``);
    fast.push(`- Test:    \`pytest\``);
  }
  const seen = new Set(fast.map(l => l.toLowerCase()));
  for (const v of a.verificationCommands.slice(0, 4)) {
    const formatted = `- Verify:  \`${v.command}\``;
    if (!seen.has(formatted.toLowerCase())) { fast.push(formatted); seen.add(formatted.toLowerCase()); }
  }
  if (!fast.length) fast.push(`- (No scripts detected — fill in run/test commands here.)`);
  lines.push(...fast);
  lines.push('');

  lines.push(`## Architecture map`);
  const touched = collectTopDirs(a.reads.concat(a.edits).concat(a.writes));
  if (touched.length) {
    for (const d of touched.slice(0, 8)) lines.push(`- \`${d.dir}/\`: ${d.hint}`);
  } else {
    lines.push(`- Touched directories were not localised in the source session. Fill in by hand.`);
  }
  lines.push('');

  lines.push(`## Working rules`);
  const rules = [];
  if (a.reads.length && a.reads[0].count >= 3) {
    rules.push(`Explore unfamiliar files before editing. The last session re-read \`${shortPath(a.reads[0].target)}\` ${a.reads[0].count} times — read once, plan, then edit.`);
  }
  if (a.repeatedRunSummary.high >= 1) {
    rules.push(`If the same tool runs ${a.repeatedRunSummary.high === 1 ? 'three times in a row' : '>=3 times in a row'} on the same target, stop and re-plan. The last session had ${a.repeatedRunSummary.high} high-confidence repeated-run signal${a.repeatedRunSummary.high === 1 ? '' : 's'}.`);
  } else if (a.repeatedRunSummary.medium >= 2) {
    rules.push(`Batch identical tool calls inside one model request — the repeated-run detector saw ${a.repeatedRunSummary.medium} medium-confidence batches last session.`);
  }
  if (a.verificationCommands.length) {
    rules.push(`Verify with \`${a.verificationCommands[0].command}\` before declaring work done. It is the verification step the last session actually used.`);
  } else {
    rules.push(`Prefer the smallest meaningful verification before finalising. Add a verification command to this file when one becomes the project default.`);
  }
  if (a.dangerousCommands.length) {
    rules.push(`Never run ${a.dangerousCommands.slice(0, 2).map(d => '`' + d.command.slice(0, 40) + '`').join(' or ')} — the last session triggered the dangerous-command guard.`);
  }
  rules.push(`Do not write secrets to logs, generated files, or commits. DashClaw scans generated content but the rule still applies to hand-written code.`);
  const capped = rules.slice(0, 5);
  for (const r of capped) lines.push(`- ${r}`);
  lines.push('');

  lines.push(`## Deeper context`);
  lines.push(`- Session notes: \`.claude/dashclaw/session-notes/\` — detail per session, not for root memory.`);
  lines.push(`- Path rules:    \`.claude/rules/\` — rules scoped to specific subtrees.`);
  lines.push(`- Hooks:         \`.claude/hooks/\` — guard scripts; review before activating in \`settings.json\`.`);
  lines.push(`- Recipes:       \`.claude/dashclaw/recipes/\` — next-session starting prompts.`);
  lines.push('');

  lines.push(`---`);
  lines.push(`Generated by DashClaw Code Sessions from session \`${(a.session && a.session.session_uuid) || '?'}\`.`);
  lines.push(`Parser version: \`${a.cost.parserVersion || '?'}\`.`);
  lines.push(`Generated at: \`${a.generatedAt}\`.`);
  lines.push(`Review before committing.`);

  let out = lines;
  if (out.length > MAX_LINES_HARD) {
    out = out.slice(0, MAX_LINES_HARD - 2);
    out.push('');
    out.push(`<!-- truncated to keep CLAUDE.md under ${MAX_LINES_HARD} lines; see .claude/dashclaw/session-notes/ for detail -->`);
  }

  return {
    path: 'CLAUDE.md',
    kind: 'root-claude-md',
    title: 'Root Claude Code memory',
    content: out.join('\n') + '\n',
    reason: 'Concise project doorway — what the next session needs to start fast. Heavy detail is intentionally pushed into deeper files.',
    confidence: a.confidence.contextGap,
    commitRecommendation: 'commit',
    group: 'recommended_now',
    lineCount: out.length,
    targetLines: TARGET_LINES_MAX,
    hardMaxLines: MAX_LINES_HARD,
  };
}

function shortPath(p) {
  if (!p) return '';
  const parts = String(p).split(/[\\/]/);
  if (parts.length <= 3) return p;
  return '.../' + parts.slice(-3).join('/');
}

function collectTopDirs(targets) {
  const dirs = new Map();
  for (const t of targets) {
    const segs = String(t.target || '').split(/[\\/]/).filter(Boolean);
    if (!segs.length) continue;
    let dir = segs[0];
    if (/^[A-Za-z]:$/.test(dir)) dir = segs[1] || dir;
    if (dir === 'Projects' || dir === 'Users' || dir === '~') dir = segs[2] || dir;
    const key = dir;
    const cur = dirs.get(key) || { dir: key, count: 0, files: 0, exts: new Set() };
    cur.count += t.count;
    cur.files += 1;
    const ext = path.extname(t.target).toLowerCase();
    if (ext) cur.exts.add(ext);
    dirs.set(key, cur);
  }
  return [...dirs.values()]
    .map(d => ({ dir: d.dir, hint: hintForDir(d) }))
    .filter(d => !!d.dir)
    .sort((a, b) => a.dir.localeCompare(b.dir));
}

function hintForDir(d) {
  const exts = [...d.exts];
  const has = (e) => exts.includes(e);
  if (d.dir === 'src') return 'source code';
  if (d.dir === 'tests' || d.dir === 'test') return 'tests';
  if (d.dir === 'public' || d.dir === 'frontend' || d.dir === 'web' || d.dir === 'ui') return 'frontend assets';
  if (d.dir === 'docs' || has('.md')) return 'docs';
  if (d.dir === 'scripts') return 'helper scripts';
  if (d.dir === 'migrations' || d.dir === 'db') return 'data layer';
  if (has('.ts') || has('.tsx') || has('.js')) return 'source code';
  if (has('.py')) return 'python source';
  return `${d.files} files re-read in session`;
}
