import { spawn } from 'node:child_process';
import path from 'node:path';
import type { Plugin } from 'vite';

const NAV_PROTOTYPE_ID = 'oneos-prototype-nav';
const SYNC_SCRIPT = 'scripts/sync-prototype-nav-registry.mjs';
const DEBOUNCE_MS = 900;

function extractPrototypeId(filePath: string, projectRoot: string): string | null {
  const relative = path.relative(projectRoot, filePath).split(path.sep).join('/');
  const match = relative.match(/^src\/prototypes\/([^/]+)\//u);
  if (!match) return null;
  const prototypeId = match[1];
  if (prototypeId === NAV_PROTOTYPE_ID) return null;
  if (relative.includes('prototype-registry.json') || relative.includes('nav-menu.json')) return null;
  return prototypeId;
}

export function createPrototypeNavRegistryPlugin(projectRoot = process.cwd()): Plugin {
  let debounceTimer: ReturnType<typeof setTimeout> | null = null;
  let running = false;
  let queuedPrototypeId: string | null = null;

  const runSync = (prototypeId: string | null) => {
    if (!prototypeId) return;
    queuedPrototypeId = prototypeId;
    if (debounceTimer) clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => {
      if (running) return;
      running = true;
      const targetId = queuedPrototypeId;
      queuedPrototypeId = null;
      const child = spawn(
        process.execPath,
        [
          path.join(projectRoot, SYNC_SCRIPT),
          '--prototype',
          targetId || '',
          '--quiet',
          '--skip-directory-sync',
          `--project-root=${projectRoot}`,
        ],
        { cwd: projectRoot, stdio: 'ignore' },
      );
      child.on('exit', () => {
        running = false;
        if (queuedPrototypeId) runSync(queuedPrototypeId);
      });
    }, DEBOUNCE_MS);
  };

  return {
    name: 'axhub-prototype-nav-registry',
    apply: 'serve',
    configureServer(server) {
      const handle = (filePath: string) => {
        const prototypeId = extractPrototypeId(filePath, projectRoot);
        if (prototypeId) runSync(prototypeId);
      };
      server.watcher.on('change', handle);
      server.watcher.on('add', handle);
    },
  };
}
