/**
 * Path list of Cinny UI modules the playground can open.
 */
const componentModules = import.meta.glob(
  [
    '../app/components/**/*.{tsx,ts}',
    '../app/features/**/*.{tsx,ts}',
  ],
  { eager: false }
);

export type CatalogEntry = {
  id: string;
  label: string;
  importPath: string;
  /** Path under cinny/, e.g. src/app/components/.../Foo.tsx */
  filePath: string;
};

function toFilePath(viteKey: string): string | null {
  const normalized = viteKey.replace(/\\/g, '/');
  let rel = normalized;
  const appIdx = rel.indexOf('/app/');
  if (appIdx !== -1) {
    rel = `src${rel.slice(appIdx)}`;
  } else if (rel.startsWith('../app/')) {
    rel = `src/${rel.slice('../'.length)}`;
  } else if (rel.startsWith('../')) {
    rel = `src/app/${rel.slice('../'.length)}`;
  } else {
    return null;
  }
  if (!/\.(tsx|ts)$/.test(rel)) return null;
  return rel;
}

function toImportPath(viteKey: string): string | null {
  const normalized = viteKey.replace(/\\/g, '/');
  let rel = normalized;
  const appIdx = rel.indexOf('/app/');
  if (appIdx !== -1) {
    rel = rel.slice(appIdx + '/app/'.length);
  } else if (rel.startsWith('../')) {
    rel = rel.replace(/^\.\.\//, '');
  }
  rel = rel.replace(/\.(tsx|ts)$/, '');
  if (rel.endsWith('.css') || rel.includes('.css')) return null;
  return `@cinny/app/${rel}`;
}

function toLabel(importPath: string): string {
  return importPath.replace(/^@cinny\//, '');
}

export function getCatalog(): CatalogEntry[] {
  const entries: CatalogEntry[] = [];
  for (const key of Object.keys(componentModules)) {
    if (/\.css(\.ts)?$/.test(key)) continue;
    if (/\.test\./.test(key) || /\.spec\./.test(key)) continue;
    // Prefer UI modules — plain .ts files are usually helpers/hooks, not preview targets.
    if (key.endsWith('.ts') && !key.endsWith('.tsx')) continue;
    const importPath = toImportPath(key);
    const filePath = toFilePath(key);
    if (!importPath || !filePath) continue;
    entries.push({
      id: key,
      label: toLabel(importPath),
      importPath,
      filePath,
    });
  }
  return entries.sort((a, b) => a.label.localeCompare(b.label));
}

/**
 * Generated harness source. Prefer a clean named import the user can edit.
 */
export function harnessForModule(importPath: string): string {
  const nameGuess =
    importPath
      .split('/')
      .pop()
      ?.replace(/[^a-zA-Z0-9_$]/g, '') || 'Component';

  if (nameGuess === 'RoomInput') {
    return `/**
 * Preview harness for ${importPath}
 *
 * Uses the room from PlaygroundProviders (mock or live Paarrot session).
 * Switch to the Component tab to edit the real source.
 */
import { useRef } from 'react';
import { RoomInput } from '${importPath}';
import { useEditor } from '@cinny/app/components/editor';
import { useRoom } from '@cinny/app/hooks/useRoom';

export default function Preview() {
  const editor = useEditor();
  const dropRef = useRef<HTMLDivElement>(null);
  const room = useRoom();

  return (
    <div ref={dropRef} style={{ width: '100%' }}>
      <RoomInput
        editor={editor}
        fileDropContainerRef={dropRef}
        roomId={room.roomId}
        room={room}
      />
    </div>
  );
}
`;
  }

  return `/**
 * Preview harness for ${importPath}
 *
 * This only mounts the component. To edit labels/strings/markup, switch to the
 * Component tab (writes the real source file under src/app/…).
 */
import { ${nameGuess} } from '${importPath}';

export default function Preview() {
  return <${nameGuess} />;
}
`;
}
