import type { Dirent } from "node:fs";
import fs from "node:fs/promises";
import path from "node:path";
import type { SkillSource } from "./types.ts";

/** 프론트매터를 본문과 분리한다. yaml 파서를 끌어오지 않으려고 필요한 필드만 얕게 읽는다. */
export function splitFrontmatter(md: string): { fm: Record<string, string>; body: string } {
  const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(md);
  if (!m) return { fm: {}, body: md };
  const fm: Record<string, string> = {};
  for (const line of (m[1] ?? "").split(/\r?\n/)) {
    const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
    if (!kv) continue;
    let v = (kv[2] ?? "").trim();
    // 따옴표로 감싼 값의 따옴표만 벗긴다
    if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) {
      v = v.slice(1, -1);
    }
    fm[kv[1] as string] = v;
  }
  return { fm, body: md.slice(m[0].length) };
}

async function walk(dir: string, base = dir): Promise<string[]> {
  const out: string[] = [];
  let entries: Dirent[];
  try {
    entries = await fs.readdir(dir, { withFileTypes: true });
  } catch {
    return out;
  }
  for (const e of entries) {
    const full = path.join(dir, e.name);
    if (e.isDirectory()) out.push(...(await walk(full, base)));
    else out.push(path.relative(base, full).split(path.sep).join("/"));
  }
  return out.sort();
}

/**
 * 스킬 원본 디렉터리를 읽어 메모리에 올린다.
 * SKILL.md 는 필수, 나머지(references/ 등)는 전부 그대로 따라간다.
 */
export async function loadSkillSource(root: string, version: string): Promise<SkillSource> {
  const skillMd = await fs.readFile(path.join(root, "SKILL.md"), "utf8");
  const { fm, body } = splitFrontmatter(skillMd);

  const files = new Map<string, string>();
  for (const rel of await walk(root)) {
    if (rel === "SKILL.md") continue;
    if (rel.endsWith(".orig") || rel === ".designpaca_version") continue;
    files.set(rel, await fs.readFile(path.join(root, rel), "utf8"));
  }

  return {
    version,
    skillMd,
    files,
    body: body.trim(),
    description: fm["description"] ?? "웹 디자인 파이프라인 스킬",
  };
}
