import {
  WU_STATUS,
  getConfig
} from "./chunk-V6OJGLBA.js";
import "./chunk-RXRKBBSM.js";
import "./chunk-3RG5ZIWI.js";

// ../core/dist/wu-duplicate-id-detector.js
import { readdirSync, readFileSync, writeFileSync, existsSync, renameSync } from "fs";
import path from "path";
import { parse, stringify } from "yaml";
var WU_YAML_EXTENSION = ".yaml";
var WU_ID_PREFIX = "WU-";
var STAMP_SUFFIX = ".done";
var EVENTS_FILE = "wu-events.jsonl";
function scanYamlFiles(wuDirAbsolute) {
  const idToFiles = /* @__PURE__ */ new Map();
  if (!existsSync(wuDirAbsolute)) {
    return idToFiles;
  }
  const entries = readdirSync(wuDirAbsolute);
  for (const entry of entries) {
    if (!entry.endsWith(WU_YAML_EXTENSION))
      continue;
    const fullPath = path.join(wuDirAbsolute, entry);
    try {
      const content = readFileSync(fullPath, "utf-8");
      const doc = parse(content);
      if (!doc || typeof doc.id !== "string")
        continue;
      const id = doc.id;
      const existing = idToFiles.get(id) ?? [];
      existing.push(fullPath);
      idToFiles.set(id, existing);
    } catch {
    }
  }
  return idToFiles;
}
function findStamps(stampsDirAbsolute, id) {
  const stampFile = path.join(stampsDirAbsolute, `${id}${STAMP_SUFFIX}`);
  if (existsSync(stampFile)) {
    return [stampFile];
  }
  return [];
}
function findEvents(eventsFileAbsolute, id) {
  if (!existsSync(eventsFileAbsolute)) {
    return [];
  }
  const content = readFileSync(eventsFileAbsolute, "utf-8");
  const lines = content.split("\n");
  const results = [];
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i]?.trim();
    if (!line)
      continue;
    try {
      const event = JSON.parse(line);
      if (event.wuId === id) {
        results.push({ line: i + 1, event });
      }
    } catch {
    }
  }
  return results;
}
async function detectDuplicateIds(projectRoot) {
  const config = getConfig({ projectRoot });
  const wuDirAbsolute = path.join(projectRoot, config.directories.wuDir);
  const stampsDirAbsolute = path.join(projectRoot, config.state.stampsDir);
  const eventsFileAbsolute = path.join(projectRoot, config.state.stateDir, EVENTS_FILE);
  const idToFiles = scanYamlFiles(wuDirAbsolute);
  const duplicates = [];
  let totalWUs = 0;
  for (const [id, files] of idToFiles) {
    totalWUs += files.length;
    if (files.length > 1) {
      duplicates.push({
        id,
        files,
        stamps: findStamps(stampsDirAbsolute, id),
        events: findEvents(eventsFileAbsolute, id)
      });
    }
  }
  for (const [, files] of idToFiles) {
    if (files.length === 1) {
    }
  }
  return { totalWUs, duplicates };
}
function nextAvailableId(existingIds) {
  let candidate = 1;
  while (existingIds.has(`${WU_ID_PREFIX}${candidate}`)) {
    candidate++;
  }
  return `${WU_ID_PREFIX}${candidate}`;
}
function chooseCanonical(id, files) {
  const expectedFilename = `${id}${WU_YAML_EXTENSION}`;
  for (let i = 0; i < files.length; i++) {
    if (path.basename(files[i]) === expectedFilename) {
      return i;
    }
  }
  return 0;
}
function collectAllIds(wuDirAbsolute) {
  const ids = /* @__PURE__ */ new Set();
  if (!existsSync(wuDirAbsolute))
    return ids;
  const entries = readdirSync(wuDirAbsolute);
  for (const entry of entries) {
    if (!entry.endsWith(WU_YAML_EXTENSION))
      continue;
    const fullPath = path.join(wuDirAbsolute, entry);
    try {
      const content = readFileSync(fullPath, "utf-8");
      const doc = parse(content);
      if (doc && typeof doc.id === "string") {
        ids.add(doc.id);
      }
    } catch {
    }
  }
  return ids;
}
function updateEvents(eventsFileAbsolute, oldId, newId, duplicateLane) {
  if (!existsSync(eventsFileAbsolute))
    return false;
  const content = readFileSync(eventsFileAbsolute, "utf-8");
  const lines = content.split("\n");
  let modified = false;
  const newLines = [];
  for (const rawLine of lines) {
    const line = rawLine.trim();
    if (!line) {
      newLines.push(rawLine);
      continue;
    }
    try {
      const event = JSON.parse(line);
      if (event.wuId === oldId) {
        if (duplicateLane && typeof event.lane === "string" && event.lane !== duplicateLane) {
          newLines.push(rawLine);
          continue;
        }
        event.wuId = newId;
        newLines.push(JSON.stringify(event));
        modified = true;
      } else {
        newLines.push(rawLine);
      }
    } catch {
      newLines.push(rawLine);
    }
  }
  if (modified) {
    writeFileSync(eventsFileAbsolute, newLines.join("\n"), "utf-8");
  }
  return modified;
}
async function repairDuplicateIds(projectRoot, options) {
  const report = await detectDuplicateIds(projectRoot);
  if (report.duplicates.length === 0) {
    return { applied: false, mappings: [] };
  }
  const config = getConfig({ projectRoot });
  const wuDirAbsolute = path.join(projectRoot, config.directories.wuDir);
  const stampsDirAbsolute = path.join(projectRoot, config.state.stampsDir);
  const eventsFileAbsolute = path.join(projectRoot, config.state.stateDir, EVENTS_FILE);
  const allIds = collectAllIds(wuDirAbsolute);
  const mappings = [];
  for (const group of report.duplicates) {
    const canonicalIdx = chooseCanonical(group.id, group.files);
    for (let i = 0; i < group.files.length; i++) {
      if (i === canonicalIdx)
        continue;
      const duplicateFile = group.files[i];
      const newId = nextAvailableId(allIds);
      allIds.add(newId);
      if (!options.apply) {
        mappings.push({
          oldId: group.id,
          newId,
          renamedFile: duplicateFile,
          touchedFiles: []
        });
        continue;
      }
      const touchedFiles = [];
      try {
        const content = readFileSync(duplicateFile, "utf-8");
        const doc = parse(content);
        const duplicateLane = typeof doc.lane === "string" ? doc.lane : void 0;
        doc.id = newId;
        writeFileSync(duplicateFile, stringify(doc, { lineWidth: 0 }), "utf-8");
        touchedFiles.push(duplicateFile);
        const newFilePath = path.join(wuDirAbsolute, `${newId}${WU_YAML_EXTENSION}`);
        renameSync(duplicateFile, newFilePath);
        touchedFiles[touchedFiles.length - 1] = newFilePath;
        const oldStampPath = path.join(stampsDirAbsolute, `${group.id}${STAMP_SUFFIX}`);
        const newStampPath = path.join(stampsDirAbsolute, `${newId}${STAMP_SUFFIX}`);
        if (existsSync(oldStampPath)) {
          if (doc.status === WU_STATUS.DONE) {
            writeFileSync(newStampPath, "", "utf-8");
            touchedFiles.push(newStampPath);
          }
        }
        if (updateEvents(eventsFileAbsolute, group.id, newId, duplicateLane)) {
          touchedFiles.push(eventsFileAbsolute);
        }
        mappings.push({
          oldId: group.id,
          newId,
          renamedFile: newFilePath,
          touchedFiles
        });
      } catch {
      }
    }
  }
  return {
    applied: options.apply,
    mappings
  };
}
export {
  detectDuplicateIds,
  repairDuplicateIds
};
