import fs from "fs/promises";
import path from "path";
import { writeFileIfMissing } from "../util/scaffold-files";

export interface CollectionCreateOptions {
  name?: string;
  schema?: string;
}

function isSafeCollectionName(value: string): boolean {
  return /^[A-Za-z0-9_-]+$/.test(value);
}

function normalizeSchema(value?: string): "markdown" | null {
  if (!value) return "markdown";

  switch (value.toLowerCase()) {
    case "markdown":
    case "md":
      return "markdown";
    default:
      return null;
  }
}

function buildCollectionSnippet(name: string): string {
  return `    ${JSON.stringify(name)}: defineCollection({
      loader: glob({ pattern: "content/${name}/**/*.md" }),
    }),
`;
}

function buildCollectionConfig(name: string): string {
  return `import { defineCollection, defineContentConfig, glob } from "@mandujs/core/content";

export default defineContentConfig({
  collections: {
${buildCollectionSnippet(name)}  },
});
`;
}

function buildCollectionExample(name: string): string {
  const today = new Date().toISOString().slice(0, 10);
  return `---
title: Hello ${name}
description: First entry in the ${name} collection
date: ${today}
tags:
  - mandu
  - ${name}
draft: false
---

# Hello ${name}

This file was generated by \`mandu collection create ${name}\`.

- Keep your frontmatter fields consistent across entries.
- Expand \`content.config.ts\` with a schema once the shape stabilizes.
`;
}

async function updateExistingConfig(rootDir: string, name: string): Promise<"updated" | "already-configured" | "manual"> {
  const filePath = path.join(rootDir, "content.config.ts");
  const content = await fs.readFile(filePath, "utf8");

  if (
    content.includes(`"content/${name}/**/*.md"`) ||
    content.includes(`'content/${name}/**/*.md'`) ||
    new RegExp(`["']${name}["']\\s*:`).test(content)
  ) {
    return "already-configured";
  }

  let nextContent = content;

  const importPattern = /import\s*{([^}]+)}\s*from\s*["']@mandujs\/core\/content["'];?/;
  if (importPattern.test(nextContent)) {
    nextContent = nextContent.replace(importPattern, (_full, imports: string) => {
      const names = imports
        .split(",")
        .map((part) => part.trim())
        .filter(Boolean);

      if (!names.includes("defineCollection")) names.push("defineCollection");
      if (!names.includes("defineContentConfig")) names.push("defineContentConfig");
      if (!names.includes("glob")) names.push("glob");

      return `import { ${names.join(", ")} } from "@mandujs/core/content";`;
    });
  } else {
    nextContent = `import { defineCollection, defineContentConfig, glob } from "@mandujs/core/content";\n\n${nextContent}`;
  }

  if (!/collections\s*:\s*{/.test(nextContent)) {
    return "manual";
  }

  nextContent = nextContent.replace(/collections\s*:\s*{/, (match) => `${match}\n${buildCollectionSnippet(name)}`);
  await fs.writeFile(filePath, nextContent);
  return "updated";
}

export async function collectionCreate(options: CollectionCreateOptions = {}): Promise<boolean> {
  if (!options.name) {
    console.error("Usage: bunx mandu collection create <name> [--schema markdown]");
    return false;
  }
  if (!isSafeCollectionName(options.name)) {
    console.error("Collection name must use letters, numbers, hyphens, or underscores only");
    return false;
  }

  const schema = normalizeSchema(options.schema);
  if (!schema) {
    console.error(`Unknown collection schema: ${options.schema}`);
    console.error("Available schemas: markdown");
    return false;
  }

  const name = options.name;
  const cwd = process.cwd();
  const exampleResult = await writeFileIfMissing(
    cwd,
    `content/${name}/hello-world.md`,
    buildCollectionExample(name),
  );

  const configPath = path.join(cwd, "content.config.ts");
  let configStatus: "created" | "updated" | "already-configured" | "manual";

  try {
    await fs.access(configPath);
    configStatus = await updateExistingConfig(cwd, name);
  } catch {
    await fs.writeFile(configPath, buildCollectionConfig(name));
    configStatus = "created";
  }

  const exampleVerb = exampleResult.created ? "Created" : "Skipped existing";
  console.log(`${exampleVerb} ${exampleResult.displayPath}`);

  switch (configStatus) {
    case "created":
      console.log("Created content.config.ts");
      break;
    case "updated":
      console.log("Updated content.config.ts");
      break;
    case "already-configured":
      console.log("content.config.ts already contains this collection");
      break;
    case "manual":
      console.log("Could not safely update content.config.ts automatically");
      break;
  }

  console.log("\nNext steps:");
  console.log(`  - Add more markdown entries under content/${name}/.`);
  if (configStatus === "manual") {
    console.log(`  - Manually add a ${name} collection to content.config.ts.`);
  } else {
    console.log("  - Add a schema to content.config.ts when your frontmatter structure is stable.");
  }

  return true;
}
