// lib/validators/plan-validator.mjs
// Wraps plan-schema (heading shape) + manifest-yaml (per-step Manifest blocks).
// This is the JS equivalent of Phase 5.5 grep checks in planning-orchestrator.

import { readFileSync, existsSync } from 'node:fs';
import { sliceSteps, validatePlanHeadings, extractPlanVersion } from '../parsers/plan-schema.mjs';
import { validateAllManifests } from '../parsers/manifest-yaml.mjs';
import { issue, fail } from '../util/result.mjs';

export function validatePlanContent(text, opts = {}) {
  const strict = opts.strict !== false;
  const headRes = validatePlanHeadings(text, { strict });
  const errors = [...headRes.errors];
  const warnings = [...headRes.warnings];

  const steps = headRes.parsed?.steps || [];
  const sections = sliceSteps(text);
  const manRes = validateAllManifests(sections);
  errors.push(...manRes.errors);
  warnings.push(...manRes.warnings);

  if (steps.length > 0 && manRes.parsed.length !== steps.length) {
    errors.push(issue(
      'PLAN_MANIFEST_COUNT_MISMATCH',
      `Step count (${steps.length}) does not equal manifest count (${manRes.parsed.length})`,
    ));
  }

  const planVersion = extractPlanVersion(text);
  if (planVersion === null) {
    warnings.push(issue('PLAN_NO_VERSION', 'No plan_version detected; current target is 1.7'));
  } else if (planVersion !== '1.7') {
    warnings.push(issue('PLAN_VERSION_MISMATCH', `plan_version=${planVersion}, current target is 1.7`));
  }

  return {
    valid: errors.length === 0,
    errors,
    warnings,
    parsed: { steps, manifests: manRes.parsed, planVersion },
  };
}

export function validatePlan(filePath, opts = {}) {
  if (!existsSync(filePath)) return fail(issue('PLAN_NOT_FOUND', `File not found: ${filePath}`));
  let text;
  try { text = readFileSync(filePath, 'utf-8'); }
  catch (e) { return fail(issue('PLAN_READ_ERROR', `Cannot read ${filePath}: ${e.message}`)); }
  const r = validatePlanContent(text, opts);
  return { ...r, parsed: { ...r.parsed, filePath } };
}

if (import.meta.url === `file://${process.argv[1]}`) {
  const args = process.argv.slice(2);
  const strict = !args.includes('--soft');
  const filePath = args.find(a => !a.startsWith('--'));
  if (!filePath) {
    process.stderr.write('Usage: plan-validator.mjs [--strict|--soft] <plan.md>\n');
    process.exit(2);
  }
  const r = validatePlan(filePath, { strict });
  if (args.includes('--json')) {
    process.stdout.write(JSON.stringify({
      valid: r.valid,
      errors: r.errors,
      warnings: r.warnings,
      steps: r.parsed?.steps?.length ?? 0,
      planVersion: r.parsed?.planVersion ?? null,
    }, null, 2) + '\n');
  } else {
    process.stdout.write(`plan-validator: ${r.valid ? 'READY' : 'FAIL'} ${filePath} (${r.parsed?.steps?.length ?? 0} steps)\n`);
    for (const e of r.errors) process.stderr.write(`  ERROR  [${e.code}] ${e.message}\n`);
    for (const w of r.warnings) process.stderr.write(`  WARN   [${w.code}] ${w.message}\n`);
  }
  process.exit(r.valid ? 0 : 1);
}
