function generateReactHook(context) {
  const { model } = context;
  if (!model) {
    throw new Error("Model is required in template context");
  }
  const modelName = model.name;
  const hookName = `use${modelName}`;
  const controllerName = `${modelName}Controller`;
  const singular = modelName.charAt(0).toLowerCase() + modelName.slice(1);
  const plural = singular + "s";
  return `/**
 * ${hookName}
 *
 * Thin delegator over the canonical useApi hooks. All state flows
 * through \`['entities', '${modelName}']\` so WebSocket invalidation
 * reaches every view consuming this hook.
 */

import { useMemo } from 'react';
import {
  useEntitiesQuery,
  useExecuteOperationMutation,
} from './useApi';
import type { ${modelName} } from '../types/${modelName}';

interface ${capitalize(hookName)}Options {
  id?: string;
  list?: boolean;
  filters?: Record<string, any>;
}

export function ${hookName}(opts: ${capitalize(hookName)}Options = {}) {
  const { id, filters: _filters } = opts;

  // Canonical list query \u2014 one cache key per model. The list flag
  // is preserved for backwards compatibility but the query always
  // runs; React Query dedupes across consumers automatically.
  const query = useEntitiesQuery('${controllerName}', '${modelName}');
  const ${plural} = (query.data as ${modelName}[] | undefined) || [];

  // Single-entity lookup is client-side against the canonical list
  // so both the detail view and the list view share one source of
  // truth. If the caller needs server-side hydration for a single
  // entity, they should call useEntitiesQuery directly with a
  // filtered controller endpoint.
  const ${singular} = useMemo<${modelName} | null>(() => {
    if (!id) return null;
    for (const entity of ${plural}) {
      const entityId = (entity as any)?.id || (entity as any)?.data?.id;
      if (entityId === id) return entity;
    }
    return null;
  }, [id, ${plural}]);

  const mutation = useExecuteOperationMutation();

  return {
    ${singular},
    ${plural},
    isLoading: query.isLoading,
    error: query.error,
    refetch: () => { /* handled by useEntitiesQuery refetchInterval + WS invalidation */ },
    create: (data: Partial<${modelName}>) =>
      mutation.mutateAsync({ controllerName: '${controllerName}', operationName: 'create', data: data as Record<string, unknown> }),
    update: (args: { id: string; data: Partial<${modelName}> }) =>
      mutation.mutateAsync({ controllerName: '${controllerName}', operationName: 'update', entityId: args.id, data: args.data as Record<string, unknown> }),
    delete: (entityId: string) =>
      mutation.mutateAsync({ controllerName: '${controllerName}', operationName: 'delete', entityId, data: {} }),
    isCreating: mutation.isPending,
    isUpdating: mutation.isPending,
    isDeleting: mutation.isPending,
  };
}
`;
}
function capitalize(s) {
  return s.charAt(0).toUpperCase() + s.slice(1);
}
export {
  generateReactHook as default
};
