const fs = require("fs");
const path = require("path");
const crypto = require("crypto");

const MARKER_START = "<!-- capint:managed:start -->";
const MARKER_END = "<!-- capint:managed:end -->";

function fileHash(content) {
  return crypto.createHash("sha256").update(content).digest("hex").slice(0, 12);
}

function hasManagedBlock(content) {
  return content.includes(MARKER_START) && content.includes(MARKER_END);
}

function mergeManagedBlock(existing, incoming) {
  if (!hasManagedBlock(existing)) return null;
  const start = existing.indexOf(MARKER_START);
  const end = existing.indexOf(MARKER_END);
  if (start === -1 || end === -1 || end <= start) return null;
  const before = existing.slice(0, start + MARKER_START.length);
  const after = existing.slice(end);
  const innerStart = incoming.indexOf(MARKER_START);
  const innerEnd = incoming.indexOf(MARKER_END);
  if (innerStart === -1 || innerEnd === -1) return null;
  const inner = incoming.slice(innerStart + MARKER_START.length, innerEnd);
  return `${before}\n${inner}\n${after}`;
}

/**
 * Safe-merge policy:
 * - missing file -> created
 * - existing with managed block -> updated (merge inner)
 * - existing without managed block -> conflict (write *.capint.new.md)
 */
function applyFilePolicy({ rootDir, relativePath, content, force = false }) {
  const abs = path.join(rootDir, relativePath);
  const dir = path.dirname(abs);
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });

  if (!fs.existsSync(abs)) {
    fs.writeFileSync(abs, content, "utf-8");
    return { path: relativePath, action: "created" };
  }

  const existing = fs.readFileSync(abs, "utf-8");
  if (force) {
    fs.writeFileSync(abs, content, "utf-8");
    return { path: relativePath, action: "updated", mode: "force" };
  }

  const merged = mergeManagedBlock(existing, content);
  if (merged && merged !== existing) {
    fs.writeFileSync(abs, merged, "utf-8");
    return { path: relativePath, action: "updated", mode: "safe-merge" };
  }

  if (existing.trim() === content.trim()) {
    return { path: relativePath, action: "skipped", reason: "identical" };
  }

  const sidecar = `${relativePath}.capint.new.md`;
  const sideAbs = path.join(rootDir, sidecar);
  fs.writeFileSync(sideAbs, content, "utf-8");
  return {
    path: relativePath,
    action: "conflict",
    sidecar,
    existing_hash: fileHash(existing),
    incoming_hash: fileHash(content)
  };
}

function buildReport(results) {
  const summary = { created: 0, updated: 0, skipped: 0, conflict: 0 };
  for (const r of results) {
    if (r.action === "created") summary.created++;
    else if (r.action === "updated") summary.updated++;
    else if (r.action === "skipped") summary.skipped++;
    else if (r.action === "conflict") summary.conflict++;
  }
  return { summary, results, generated_at: new Date().toISOString() };
}

module.exports = {
  MARKER_START,
  MARKER_END,
  applyFilePolicy,
  buildReport,
  mergeManagedBlock,
  hasManagedBlock
};
