import {
  resolveCliTemplatesDir
} from "./chunk-D3UOFRSB.js";
import {
  ErrorCodes,
  createError
} from "./chunk-RXRKBBSM.js";

// src/init-scaffolding.ts
import * as fs from "fs";
import * as path from "path";

// src/merge-block.ts
var MARKERS = {
  START: "<!-- LUMENFLOW:START -->",
  END: "<!-- LUMENFLOW:END -->"
};
function detectLineEnding(content) {
  if (!content) {
    return "\n";
  }
  const crlfCount = (content.match(/\r\n/g) || []).length;
  const lfCount = (content.match(/(?<!\r)\n/g) || []).length;
  if (crlfCount === 0 && lfCount === 0) {
    return "\n";
  }
  return crlfCount >= lfCount ? "\r\n" : "\n";
}
function normalizeLineEndings(content, lineEnding) {
  const normalized = content.replace(/\r\n/g, "\n");
  if (lineEnding === "\r\n") {
    return normalized.replace(/\n/g, "\r\n");
  }
  return normalized;
}
function extractMergeBlock(content) {
  const startIndexes = [];
  const endIndexes = [];
  let pos = 0;
  while ((pos = content.indexOf(MARKERS.START, pos)) !== -1) {
    startIndexes.push(pos);
    pos += MARKERS.START.length;
  }
  pos = 0;
  while ((pos = content.indexOf(MARKERS.END, pos)) !== -1) {
    endIndexes.push(pos);
    pos += MARKERS.END.length;
  }
  if (startIndexes.length > 1) {
    return { found: false, malformed: true, malformedReason: "multiple-start" };
  }
  if (endIndexes.length > 1) {
    return { found: false, malformed: true, malformedReason: "multiple-end" };
  }
  const hasStart = startIndexes.length === 1;
  const hasEnd = endIndexes.length === 1;
  if (hasStart && !hasEnd) {
    return { found: false, malformed: true, malformedReason: "missing-end" };
  }
  if (!hasStart && hasEnd) {
    return { found: false, malformed: true, malformedReason: "missing-start" };
  }
  if (!hasStart && !hasEnd) {
    return { found: false };
  }
  const startIndex = startIndexes[0];
  const endMarkerIndex = endIndexes[0];
  const endIndex = endMarkerIndex + MARKERS.END.length;
  if (endMarkerIndex <= startIndex) {
    return { found: false, malformed: true, malformedReason: "missing-end" };
  }
  const afterStart = startIndex + MARKERS.START.length;
  const beforeEnd = endMarkerIndex;
  let blockContent = content.slice(afterStart, beforeEnd);
  blockContent = trimNewlines(blockContent);
  return {
    found: true,
    content: blockContent,
    startIndex,
    endIndex
  };
}
function insertMergeBlock(originalContent, blockContent) {
  const lineEnding = detectLineEnding(originalContent);
  const normalizedBlock = normalizeLineEndings(blockContent, lineEnding);
  let content = originalContent;
  if (!content.endsWith(lineEnding)) {
    content += lineEnding;
  }
  if (!content.endsWith(lineEnding + lineEnding) && content.trim().length > 0) {
    content += lineEnding;
  }
  const block = [MARKERS.START, normalizedBlock, MARKERS.END, ""].join(lineEnding);
  return content + block;
}
function updateMergeBlock(originalContent, newBlockContent) {
  const lineEnding = detectLineEnding(originalContent);
  const extraction = extractMergeBlock(originalContent);
  if (extraction.malformed) {
    const warning = `LumenFlow markers are malformed (${extraction.malformedReason}). Appending fresh block.`;
    const result2 = insertMergeBlock(originalContent, newBlockContent);
    return {
      content: result2,
      updated: true,
      wasInserted: true,
      warning
    };
  }
  if (!extraction.found) {
    return {
      content: insertMergeBlock(originalContent, newBlockContent),
      updated: true,
      wasInserted: true
    };
  }
  const normalizedNew = normalizeLineEndings(newBlockContent, lineEnding).trim();
  const normalizedExisting = (extraction.content || "").trim();
  if (normalizedNew === normalizedExisting) {
    return {
      content: originalContent,
      updated: false,
      unchanged: true
    };
  }
  const startIdx = extraction.startIndex ?? 0;
  const endIdx = extraction.endIndex ?? originalContent.length;
  const before = originalContent.slice(0, startIdx);
  const after = originalContent.slice(endIdx);
  const newBlock = [
    MARKERS.START,
    normalizeLineEndings(newBlockContent, lineEnding),
    MARKERS.END
  ].join(lineEnding);
  let result = before;
  if (!result.endsWith(lineEnding) && result.length > 0) {
    result += lineEnding;
  }
  result += newBlock;
  if (after.trim().length > 0) {
    if (!result.endsWith(lineEnding)) {
      result += lineEnding;
    }
    result += after;
  } else if (after.includes(lineEnding)) {
    if (!result.endsWith(lineEnding)) {
      result += lineEnding;
    }
  }
  return {
    content: result,
    updated: true
  };
}
function trimNewlines(str) {
  let start = 0;
  let end = str.length;
  while (start < end && (str[start] === "\r" || str[start] === "\n")) {
    start++;
  }
  while (end > start && (str[end - 1] === "\r" || str[end - 1] === "\n")) {
    end--;
  }
  return str.slice(start, end);
}

// src/init-scaffolding.ts
function processTemplate(content, tokens) {
  let output = content;
  for (const [key, value] of Object.entries(tokens)) {
    output = output.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value);
  }
  return output;
}
function getRelativePath(targetDir, filePath) {
  return path.relative(targetDir, filePath).split(path.sep).join("/");
}
function getTemplatesDir() {
  return resolveCliTemplatesDir();
}
function loadTemplate(templatePath) {
  const templatesDir = getTemplatesDir();
  const fullPath = path.join(templatesDir, templatePath);
  if (!fs.existsSync(fullPath)) {
    throw createError(ErrorCodes.FILE_NOT_FOUND, `Template not found: ${templatePath}`);
  }
  return fs.readFileSync(fullPath, "utf-8");
}
function resolveBooleanToFileMode(mode) {
  if (typeof mode === "boolean") {
    return mode ? "force" : "skip";
  }
  return mode;
}
function handleMergeMode(filePath, content, result, relativePath) {
  const existingContent = fs.readFileSync(filePath, "utf-8");
  const mergeResult = updateMergeBlock(existingContent, content);
  if (mergeResult.unchanged) {
    result.skipped.push(relativePath);
    return;
  }
  if (mergeResult.warning) {
    result.warnings?.push(`${relativePath}: ${mergeResult.warning}`);
  }
  fs.writeFileSync(filePath, mergeResult.content);
  result.merged?.push(relativePath);
}
function writeNewFile(filePath, content, result, relativePath) {
  const parentDir = path.dirname(filePath);
  if (!fs.existsSync(parentDir)) {
    fs.mkdirSync(parentDir, { recursive: true });
  }
  fs.writeFileSync(filePath, content);
  result.created.push(relativePath);
}
async function createDirectory(dirPath, result, targetDir) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
    result.created.push(getRelativePath(targetDir, dirPath));
  }
}
async function createFile(filePath, content, mode, result, targetDir) {
  const relativePath = getRelativePath(targetDir, filePath);
  const resolvedMode = resolveBooleanToFileMode(mode);
  result.merged = result.merged ?? [];
  result.warnings = result.warnings ?? [];
  result.overwritten = result.overwritten ?? [];
  const fileExists = fs.existsSync(filePath);
  if (fileExists && resolvedMode === "skip") {
    result.skipped.push(relativePath);
    return;
  }
  if (fileExists && resolvedMode === "merge") {
    handleMergeMode(filePath, content, result, relativePath);
    return;
  }
  if (fileExists && resolvedMode === "force") {
    result.overwritten.push(relativePath);
  }
  writeNewFile(filePath, content, result, relativePath);
}
async function createExecutableScript(filePath, content, mode, result, targetDir) {
  const relativePath = getRelativePath(targetDir, filePath);
  const resolvedMode = resolveBooleanToFileMode(mode);
  result.merged = result.merged ?? [];
  result.warnings = result.warnings ?? [];
  result.overwritten = result.overwritten ?? [];
  const fileExists = fs.existsSync(filePath);
  if (fileExists && resolvedMode === "skip") {
    result.skipped.push(relativePath);
    return;
  }
  if (fileExists && (resolvedMode === "force" || resolvedMode === "merge")) {
    result.overwritten.push(relativePath);
  }
  const parentDir = path.dirname(filePath);
  if (!fs.existsSync(parentDir)) {
    fs.mkdirSync(parentDir, { recursive: true });
  }
  fs.writeFileSync(filePath, content, { mode: 493 });
  result.created.push(relativePath);
}

export {
  processTemplate,
  loadTemplate,
  createDirectory,
  createFile,
  createExecutableScript
};
