/**
 * useApi Hooks Generator
 * Generates React Query hooks matching the @specverse/runtime RuntimeViewProviderValue contract
 */

export interface UseApiHooksGeneratorContext {
  spec: any;
  manifest: any;
}

export async function generate(context: UseApiHooksGeneratorContext): Promise<string> {
  return `/**
 * useApi - React Query Hooks
 *
 * Hooks match the @specverse/runtime RuntimeViewProviderValue contract.
 * These are passed to RuntimeViewProvider and called by runtime components.
 */

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
  getModelSchema,
  listEntities,
  executeOperation,
  transitionState
} from '../lib/apiClient';
import type { ModelSchema, Entity, ApiResponse } from '../types/api';

/**
 * Query hook for model schema
 */
export function useModelSchemaQuery(modelName: string | null) {
  return useQuery({
    queryKey: ['modelSchema', modelName],
    queryFn: async (): Promise<ModelSchema> => {
      if (!modelName) throw new Error('Model name is required');
      return await getModelSchema(modelName);
    },
    enabled: !!modelName,
    staleTime: 5 * 60 * 1000,
    refetchOnWindowFocus: false
  });
}

/**
 * Query hook for entities
 */
export function useEntitiesQuery(controllerName: string | null, modelName: string | null) {
  return useQuery({
    queryKey: ['entities', modelName],
    queryFn: async (): Promise<Entity[]> => {
      if (!controllerName || !modelName) {
        throw new Error('Controller and model names are required');
      }
      return await listEntities(controllerName);
    },
    enabled: !!controllerName && !!modelName,
    refetchInterval: 5000
  });
}

/**
 * Mutation hook for executing operations
 * Matches RuntimeViewProviderValue.useExecuteOperationMutation contract:
 *   { controllerName, operationName, data, entityId? }
 */
export function useExecuteOperationMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({
      controllerName,
      operationName,
      data,
      params,
      entityId
    }: {
      controllerName: string;
      operationName: string;
      data?: Record<string, any>;
      params?: Record<string, any>;
      entityId?: string;
    }): Promise<ApiResponse> => {
      // Merge: accept both 'data' and 'params' for compatibility
      const mergedParams = { ...(data || params || {}) };
      if (entityId) mergedParams.id = entityId;
      return executeOperation(controllerName, operationName, mergedParams);
    },
    onSuccess: (_data, variables) => {
      const modelName = variables.controllerName.replace(/Controller$/, '');
      queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
    }
  });
}

/**
 * Mutation hook for lifecycle transitions
 * Matches RuntimeViewProviderValue.useTransitionStateMutation contract:
 *   { controllerName, entityId, targetState }
 */
export function useTransitionStateMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({
      controllerName,
      modelName,
      entityId,
      targetState,
      toState,
      lifecycleName
    }: {
      controllerName?: string;
      modelName?: string;
      entityId: string;
      targetState?: string;
      toState?: string;
      lifecycleName?: string;
    }): Promise<ApiResponse> => {
      // Accept both field names for compatibility
      const model = modelName || controllerName?.replace(/Controller$/, '') || '';
      const state = targetState || toState || '';
      return transitionState(model, entityId, state, lifecycleName);
    },
    onSuccess: (_data, variables) => {
      const model = variables.modelName || variables.controllerName?.replace(/Controller$/, '') || '';
      queryClient.invalidateQueries({ queryKey: ['entities', model] });
    }
  });
}

/**
 * Hook for invalidating all queries
 */
export function useInvalidateAll() {
  const queryClient = useQueryClient();
  return () => queryClient.invalidateQueries();
}
`;
}
