import { readFileSync, readdirSync, writeFileSync, mkdirSync, existsSync } from 'fs';
import { join } from 'path';
import matter from 'gray-matter';
import type { Plugin } from 'vite';
import type { SkillMeta } from './src/engine/types';

const SKILLS_DIR = 'skills';
const STYLE_GUIDES_DIR = 'skills/style-guides';
const OUTPUT_DIR = 'src/_generated';
const OUTPUT_FILE = 'skill-registry.ts';
const STYLE_GUIDE_OUTPUT_FILE = 'style-guide-registry.ts';
function scanMarkdownFiles(dir: string, excludeDirs: string[] = []): string[] {
  const results: string[] = [];
  if (!existsSync(dir)) return results;
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
    const fullPath = join(dir, entry.name);
    if (entry.isDirectory()) {
      if (
        excludeDirs.some(
          (ex) => fullPath === ex || fullPath.endsWith(`/${ex}`) || fullPath.endsWith(`\\${ex}`),
        )
      )
        continue;
      results.push(...scanMarkdownFiles(fullPath, excludeDirs));
    } else if (entry.name.endsWith('.md')) {
      results.push(fullPath);
    }
  }
  return results;
}

function parseFrontmatter(filePath: string): { meta: SkillMeta; content: string } | null {
  const raw = readFileSync(filePath, 'utf-8');
  const { data, content } = matter(raw);

  if (!data.name || !data.phase) {
    console.warn(
      `[vite-plugin-skills] Skipping ${filePath}: missing required frontmatter (name, phase)`,
    );
    return null;
  }

  return {
    meta: {
      name: data.name,
      description: data.description ?? '',
      phase: Array.isArray(data.phase) ? data.phase : [data.phase],
      trigger: data.trigger ?? null,
      priority: data.priority ?? 50,
      budget: data.budget ?? 2000,
      category: data.category ?? 'domain',
    },
    content: content.trim(),
  };
}

function generateRegistry(packageRoot: string): string {
  const skillsDir = join(packageRoot, SKILLS_DIR);
  const styleGuidesAbsDir = join(packageRoot, STYLE_GUIDES_DIR);
  if (!existsSync(skillsDir))
    return "import type { SkillRegistryEntry } from '../engine/types'\n\nexport const skillRegistry: SkillRegistryEntry[] = []\n";

  const files = scanMarkdownFiles(skillsDir, [styleGuidesAbsDir]);
  const entries: Array<{ meta: SkillMeta; content: string }> = [];

  for (const file of files) {
    const parsed = parseFrontmatter(file);
    if (parsed) entries.push(parsed);
  }

  entries.sort((a, b) => a.meta.priority - b.meta.priority);

  const lines = [
    '// Auto-generated by vite-plugin-skills — DO NOT EDIT',
    `// Generated at: ${new Date().toISOString()}`,
    `// Source: ${entries.length} skill files from skills/`,
    '',
    "import type { SkillRegistryEntry } from '../engine/types'",
    '',
    `export const skillRegistry: SkillRegistryEntry[] = ${JSON.stringify(
      entries.map((e) => ({ meta: e.meta, content: e.content })),
      null,
      2,
    )}`,
    '',
  ];

  return lines.join('\n');
}

function generateStyleGuideRegistry(packageRoot: string): string {
  const styleGuidesDir = join(packageRoot, STYLE_GUIDES_DIR);
  if (!existsSync(styleGuidesDir))
    return "import type { ParsedStyleGuide } from '../style-guide/style-guide-types'\n\nexport const styleGuideRegistry: ParsedStyleGuide[] = []\n";

  const files = scanMarkdownFiles(styleGuidesDir);
  const entries: Array<{ name: string; tags: string[]; platform: string; content: string }> = [];

  for (const file of files) {
    const raw = readFileSync(file, 'utf-8');
    const { data, content } = matter(raw);

    if (!data.name || !data.tags || !data.platform) {
      console.warn(
        `[vite-plugin-skills] Skipping style guide ${file}: missing required frontmatter (name, tags, platform)`,
      );
      continue;
    }

    entries.push({
      name: data.name,
      tags: Array.isArray(data.tags) ? data.tags : [data.tags],
      platform: data.platform,
      content: content.trim(),
    });
  }

  entries.sort((a, b) => a.name.localeCompare(b.name));

  const lines = [
    '// Auto-generated by vite-plugin-skills — DO NOT EDIT',
    `// Generated at: ${new Date().toISOString()}`,
    `// Source: ${entries.length} style guide files from skills/style-guides/`,
    '',
    "import type { ParsedStyleGuide } from '../style-guide/style-guide-types'",
    '',
    `export const styleGuideRegistry: ParsedStyleGuide[] = ${JSON.stringify(
      entries.map((e) => ({
        name: e.name,
        tags: e.tags,
        platform: e.platform,
        content: e.content,
      })),
      null,
      2,
    )}`,
    '',
  ];

  return lines.join('\n');
}

export function compileSkills(packageRoot: string): void {
  const outDir = join(packageRoot, OUTPUT_DIR);
  mkdirSync(outDir, { recursive: true });
  const code = generateRegistry(packageRoot);
  writeFileSync(join(outDir, OUTPUT_FILE), code, 'utf-8');
  const styleGuideCode = generateStyleGuideRegistry(packageRoot);
  writeFileSync(join(outDir, STYLE_GUIDE_OUTPUT_FILE), styleGuideCode, 'utf-8');
}

export function vitePluginSkills(packageRoot: string): Plugin {
  return {
    name: 'vite-plugin-skills',
    buildStart() {
      compileSkills(packageRoot);
    },
    handleHotUpdate({ file }) {
      if (file.includes(join(packageRoot, SKILLS_DIR)) && file.endsWith('.md')) {
        compileSkills(packageRoot);
        return [];
      }
    },
    configureServer(server) {
      server.watcher.add(join(packageRoot, STYLE_GUIDES_DIR));
    },
  };
}
