import {
  MEMORY_PATTERNS,
  loadMemory
} from "./chunk-DFR4DJBM.js";
import {
  LUMENFLOW_MEMORY_PATHS
} from "./chunk-4N74J3UT.js";
import {
  ErrorCodes,
  createError
} from "./chunk-RXRKBBSM.js";

// ../memory/dist/mem-recover-core.js
import fs from "fs/promises";
import path from "path";
import { parse as parseYaml } from "yaml";
var DEFAULT_MAX_SIZE = 8192;
var NODE_TYPE_CHECKPOINT = "checkpoint";
var CONSTRAINTS_FILENAME = "constraints.md";
var TIMESTAMP_UNKNOWN = "unknown";
var MAX_ACCEPTANCE_ITEMS = 8;
var MAX_CODE_PATH_ITEMS = 10;
var ERROR_MESSAGES = {
  WU_ID_REQUIRED: "wuId is required",
  WU_ID_EMPTY: "wuId cannot be empty",
  WU_ID_INVALID: "Invalid WU ID format. Expected pattern: WU-XXX (e.g., WU-1234)"
};
var SECTION_HEADERS = {
  RECOVERY_TITLE: "POST-COMPACTION RECOVERY",
  LAST_CHECKPOINT: "Last Checkpoint",
  ACCEPTANCE_CRITERIA: "Acceptance Criteria",
  CODE_PATHS: "Code Paths",
  FILES_CHANGED: "Files Changed",
  CRITICAL_RULES: "Critical Rules (DO NOT FORGET)",
  CLI_COMMANDS: "CLI Commands",
  NEXT_ACTION: "Next Action"
};
var ESSENTIAL_CLI_COMMANDS = `| Command | Purpose |
|---------|---------|
| pnpm wu:status --id WU-XXX | Check WU status and location |
| pnpm wu:brief --id WU-XXX | Generate fresh agent handoff prompt |
| pnpm gates | Run quality gates before completion |
| pnpm mem:checkpoint | Save progress checkpoint |`;
var FALLBACK_CONSTRAINTS = `1. **Worktree Discipline**: Work only in worktrees, treat main as read-only
2. **WUs Are Specs**: Respect code_paths boundaries, no feature creep
3. **Docs-Only vs Code**: Documentation WUs use --docs-only gates
4. **LLM-First Inference**: Use LLMs for semantic tasks, no brittle regex
5. **Gates Required**: Run pnpm gates before wu:done
6. **Safety & Governance**: No secrets in code, stop-and-ask for sensitive ops
7. **Test Ratchet**: NEW test failures block, pre-existing show warning only`;
function validateWuId(wuId) {
  if (wuId == null) {
    throw createError(ErrorCodes.VALIDATION_ERROR, ERROR_MESSAGES.WU_ID_REQUIRED);
  }
  if (wuId === "") {
    throw createError(ErrorCodes.VALIDATION_ERROR, ERROR_MESSAGES.WU_ID_EMPTY);
  }
  if (!MEMORY_PATTERNS.WU_ID.test(wuId)) {
    throw createError(ErrorCodes.INVALID_WU_ID, ERROR_MESSAGES.WU_ID_INVALID);
  }
}
async function getLastCheckpoint(baseDir, wuId) {
  const memoryDir = path.join(baseDir, LUMENFLOW_MEMORY_PATHS.MEMORY_DIR);
  try {
    const memory = await loadMemory(memoryDir);
    const wuNodes = memory.byWu.get(wuId) ?? [];
    const checkpoints = wuNodes.filter((node) => node.type === NODE_TYPE_CHECKPOINT).sort((a, b) => {
      const aTime = new Date(a.created_at).getTime();
      const bTime = new Date(b.created_at).getTime();
      return bTime - aTime;
    });
    if (checkpoints.length === 0) {
      return null;
    }
    const latest = checkpoints[0];
    if (!latest)
      return null;
    return {
      content: latest.content,
      timestamp: latest.created_at,
      progress: latest.metadata?.progress,
      nextSteps: latest.metadata?.nextSteps,
      gitDiffStat: latest.metadata?.gitDiffStat
    };
  } catch {
    return null;
  }
}
async function loadCompactConstraints(baseDir) {
  const constraintsPath = path.join(baseDir, LUMENFLOW_MEMORY_PATHS.BASE, CONSTRAINTS_FILENAME);
  try {
    const content = await fs.readFile(constraintsPath, "utf-8");
    const rules = [];
    const sectionPattern = /### (\d+)\. ([^\n]+)\n\n\*\*Rule:\*\* ([^\n]+)/g;
    let match;
    while ((match = sectionPattern.exec(content)) !== null) {
      const [, num, title, rule] = match;
      rules.push(`${num}. **${title}**: ${rule}`);
    }
    if (rules.length > 0) {
      return rules.join("\n");
    }
    return FALLBACK_CONSTRAINTS;
  } catch {
    return FALLBACK_CONSTRAINTS;
  }
}
async function loadWuMetadata(baseDir, wuId) {
  const wuYamlPath = path.join(baseDir, "docs", "04-operations", "tasks", "wu", `${wuId}.yaml`);
  try {
    const content = await fs.readFile(wuYamlPath, "utf-8");
    const doc = parseYaml(content);
    const acceptance = Array.isArray(doc.acceptance) ? doc.acceptance.filter((s) => typeof s === "string") : [];
    const codePaths = Array.isArray(doc.code_paths) ? doc.code_paths.filter((s) => typeof s === "string") : [];
    if (acceptance.length === 0 && codePaths.length === 0) {
      return null;
    }
    return { acceptance, codePaths };
  } catch {
    return null;
  }
}
function formatRecoveryPrompt(wuId, checkpoint, constraints, cliRef, wuMetadata, maxSize) {
  const header = `# ${SECTION_HEADERS.RECOVERY_TITLE}

You are resuming work after context compaction. Your previous context was lost.
**WU:** ${wuId}

`;
  const checkpointSection = checkpoint ? `## ${SECTION_HEADERS.LAST_CHECKPOINT}
- **Progress:** ${checkpoint.content}
- **Timestamp:** ${checkpoint.timestamp}
${checkpoint.nextSteps ? `- **Next Steps:** ${checkpoint.nextSteps}` : ""}

` : `## ${SECTION_HEADERS.LAST_CHECKPOINT}
No checkpoint found for this WU.

`;
  const acceptanceItems = wuMetadata?.acceptance.slice(0, MAX_ACCEPTANCE_ITEMS) ?? [];
  const acceptanceTruncated = (wuMetadata?.acceptance.length ?? 0) > MAX_ACCEPTANCE_ITEMS;
  const acceptanceSection = acceptanceItems.length > 0 ? `## ${SECTION_HEADERS.ACCEPTANCE_CRITERIA}
${acceptanceItems.map((ac) => `- [ ] ${ac}`).join("\n")}${acceptanceTruncated ? `
- ... (${(wuMetadata?.acceptance.length ?? 0) - MAX_ACCEPTANCE_ITEMS} more \u2014 run wu:brief for full list)` : ""}

` : "";
  const codePathItems = wuMetadata?.codePaths.slice(0, MAX_CODE_PATH_ITEMS) ?? [];
  const codePathsTruncated = (wuMetadata?.codePaths.length ?? 0) > MAX_CODE_PATH_ITEMS;
  const codePathsSection = codePathItems.length > 0 ? `## ${SECTION_HEADERS.CODE_PATHS}
${codePathItems.map((cp) => `- ${cp}`).join("\n")}${codePathsTruncated ? `
- ... (${(wuMetadata?.codePaths.length ?? 0) - MAX_CODE_PATH_ITEMS} more)` : ""}

` : "";
  const gitDiffSection = checkpoint?.gitDiffStat ? `## ${SECTION_HEADERS.FILES_CHANGED}
\`\`\`
${checkpoint.gitDiffStat}
\`\`\`

` : "";
  const constraintsSection = constraints ? `## ${SECTION_HEADERS.CRITICAL_RULES}
${constraints}

` : "";
  const cliSection = cliRef ? `## ${SECTION_HEADERS.CLI_COMMANDS}
${cliRef}

` : "";
  const footer = `## ${SECTION_HEADERS.NEXT_ACTION}
Continue working on the WU using the acceptance criteria and code paths above.
If you need full context: \`pnpm wu:brief --id ${wuId}\`
`;
  const fixedContent = header + acceptanceSection + codePathsSection + gitDiffSection + constraintsSection + cliSection + footer;
  const fixedSize = Buffer.byteLength(fixedContent, "utf-8");
  if (fixedSize > maxSize) {
    const minimal = `# ${SECTION_HEADERS.RECOVERY_TITLE}
WU: ${wuId}
Run: pnpm wu:brief --id ${wuId}
`;
    return { context: minimal, truncated: true };
  }
  const remainingBudget = maxSize - fixedSize;
  const checkpointSize = Buffer.byteLength(checkpointSection, "utf-8");
  if (checkpointSize <= remainingBudget) {
    const fullContext = header + checkpointSection + acceptanceSection + codePathsSection + gitDiffSection + constraintsSection + cliSection + footer;
    return { context: fullContext, truncated: false };
  }
  const truncatedCheckpoint = `## ${SECTION_HEADERS.LAST_CHECKPOINT}
- **Progress:** (truncated - run mem:ready --wu ${wuId} for details)
- **Timestamp:** ${checkpoint?.timestamp ?? TIMESTAMP_UNKNOWN}

`;
  const context = header + truncatedCheckpoint + acceptanceSection + codePathsSection + gitDiffSection + constraintsSection + cliSection + footer;
  return { context, truncated: true };
}
async function generateRecoveryContext(options) {
  const { wuId, baseDir = ".", maxSize = DEFAULT_MAX_SIZE, includeConstraints = true, includeCLIRef = true, includeWuMetadata = true } = options;
  validateWuId(wuId);
  const checkpoint = await getLastCheckpoint(baseDir, wuId);
  const constraints = includeConstraints ? await loadCompactConstraints(baseDir) : "";
  const cliRef = includeCLIRef ? ESSENTIAL_CLI_COMMANDS : "";
  const wuMetadata = includeWuMetadata ? await loadWuMetadata(baseDir, wuId) : null;
  const { context, truncated } = formatRecoveryPrompt(wuId, checkpoint, constraints, cliRef, wuMetadata, maxSize);
  return {
    success: true,
    context,
    size: Buffer.byteLength(context, "utf-8"),
    truncated
  };
}

export {
  generateRecoveryContext
};
