/**
 * Runtime App.tsx Generator
 *
 * Generates a slim App.tsx that imports DevShell from @specverse/runtime
 * and wires it up with instance-specific API hooks.
 *
 * This replaces the 185-file static generation with ~10 files.
 */

import type { TemplateContext } from '@specverse/types';

export default function generateRuntimeAppTsx(context: TemplateContext): string {
  const { spec } = context;
  const appName = (spec as any)?.metadata?.name || (spec as any)?.name || 'SpecVerse App';

  return `import { useState, useEffect, useMemo } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import yaml from 'js-yaml';
import { RuntimeViewProvider } from '@specverse/runtime/views/react';
import { DevShell } from '@specverse/runtime/views/react';
import {
  useEntitiesQuery,
  useModelSchemaQuery,
  useExecuteOperationMutation,
  useTransitionStateMutation,
} from './hooks/useApi';
import devSpecRaw from './dev.specly?raw';

// Parse YAML spec
function parseSpec(raw: string): Record<string, unknown> {
  try {
    const parsed = yaml.load(raw);
    if (parsed && typeof parsed === 'object') {
      const obj = parsed as Record<string, unknown>;
      if (obj.components && typeof obj.components === 'object') {
        const componentName = Object.keys(obj.components)[0];
        if (componentName) {
          return { ...(obj.components as any)[componentName], componentName, _raw: obj };
        }
      }
      return obj;
    }
    return {};
  } catch {
    return {};
  }
}

const devSpec = parseSpec(devSpecRaw);

const queryClient = new QueryClient({
  defaultOptions: {
    queries: { staleTime: 5 * 60 * 1000, retry: 1 },
  },
});

function AppContent() {
  // Fetch app spec from backend API (avoids bundling spec file path issues)
  const [appSpec, setAppSpec] = useState<Record<string, unknown>>({});
  useEffect(() => {
    fetch('/api/spec')
      .then(r => r.json())
      .then(data => {
        if (data && typeof data === 'object') {
          // Flatten components wrapper if present
          if (data.components) {
            const name = Object.keys(data.components)[0];
            if (name) {
              setAppSpec({ ...data.components[name], componentName: name });
              return;
            }
          }
          setAppSpec(data);
        }
      })
      .catch(() => {});
  }, []);

  const runtimeValue = useMemo(() => ({
    useEntitiesQuery,
    useModelSchemaQuery,
    useExecuteOperationMutation,
    useTransitionStateMutation,
    entities: {},
    modelSchemas: {},
    views: [],
    spec: appSpec,
    apiBaseUrl: '/api',
  }), [appSpec]);

  return (
    <RuntimeViewProvider value={runtimeValue}>
      <DevShell
        devSpec={devSpec}
        appSpec={appSpec}
        title="${appName}"
      />
    </RuntimeViewProvider>
  );
}

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <AppContent />
    </QueryClientProvider>
  );
}
`;
}
