import { readdirSync, readFileSync, existsSync } from "node:fs";
import { join } from "node:path";
import { PACKAGE_ROOT } from "../../../util";
import { type CommandResult, success, silentFailure } from "../../lib/command-result";
import { MODULE_PATHS } from "../../lib/paths";

const MODULES_DIR = join(PACKAGE_ROOT, "src", "modules");

const DOC_TYPE_MAP: Record<string, string> = {
  command: MODULE_PATHS.docs.command,
  query: MODULE_PATHS.docs.query,
  model: MODULE_PATHS.docs.model,
  feature: MODULE_PATHS.docs.feature,
};

function listDocNames(dir: string): string[] {
  if (!existsSync(dir)) return [];
  return readdirSync(dir)
    .filter((f) => f.endsWith(".md"))
    .map((f) => f.replace(/\.md$/, ""))
    .sort();
}

function formatDocList(type: string, names: string[]): string {
  if (names.length === 0) return "";
  return `${type}: ${names.join(", ")}`;
}

export function runDocModule(
  moduleName: string,
  docType?: string,
  docName?: string,
  format = "text",
): CommandResult {
  if (!existsSync(MODULES_DIR)) {
    console.error(`Module not found: ${moduleName}`);
    return silentFailure();
  }

  const modDir = join(MODULES_DIR, moduleName);
  if (!existsSync(modDir)) {
    console.error(`Module not found: ${moduleName}`);
    const available = readdirSync(MODULES_DIR, { withFileTypes: true })
      .filter((d) => d.isDirectory())
      .map((d) => d.name)
      .sort();
    console.error(`Available modules: ${available.join(", ")}`);
    return silentFailure();
  }

  // Level 3: specific doc
  if (docType && docName) {
    const docSubdir = DOC_TYPE_MAP[docType];
    if (!docSubdir) {
      console.error(`Unknown doc type: ${docType}`);
      console.error(`Available types: ${Object.keys(DOC_TYPE_MAP).join(", ")}`);
      return silentFailure();
    }

    const docPath = join(modDir, docSubdir, `${docName}.md`);
    if (!existsSync(docPath)) {
      console.error(`Doc not found: ${moduleName}/${docType}/${docName}`);
      const available = listDocNames(join(modDir, docSubdir));
      if (available.length > 0) {
        console.error(`Available ${docType}s: ${available.join(", ")}`);
      } else {
        console.error(`No ${docType} docs found for ${moduleName}`);
      }
      return silentFailure();
    }

    const content = readFileSync(docPath, "utf-8");
    if (format === "json") {
      console.log(
        JSON.stringify({ module: moduleName, type: docType, name: docName, content }, null, 2),
      );
    } else {
      console.log(content);
    }
    return success();
  }

  // Level 2: full module detail
  const readmePath = join(modDir, "README.md");
  const readme = existsSync(readmePath) ? readFileSync(readmePath, "utf-8") : "";

  const docs: Record<string, string[]> = {};
  for (const [type, subdir] of Object.entries(DOC_TYPE_MAP)) {
    const names = listDocNames(join(modDir, subdir));
    if (names.length > 0) docs[type] = names;
  }

  if (format === "json") {
    console.log(JSON.stringify({ module: moduleName, readme, docs }, null, 2));
  } else {
    if (readme) {
      console.log(readme);
    } else {
      console.log(`# ${moduleName}\n\nNo README found.\n`);
    }

    const sections: string[] = [];
    for (const [type, names] of Object.entries(docs)) {
      sections.push(formatDocList(type, names));
    }

    if (sections.length > 0) {
      console.log("\n## Available Documentation\n");
      console.log(sections.join("\n"));
    }
  }

  return success();
}
