/**
 * useAgentTools Hook
 * Manages agent tools configuration with API integration
 * OQI-007: LLM Strategy Agent - Tools Hook
 */

import { useState, useCallback, useMemo } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '../../../lib/apiClient';
import type { AgentTool, ToolCategory } from '../components/ToolsConfigPanel';

// ============================================================================
// Types
// ============================================================================

interface UseAgentToolsOptions {
  enabled?: boolean;
}

interface UseAgentToolsReturn {
  tools: AgentTool[];
  enabledTools: AgentTool[];
  toolsByCategory: Record<ToolCategory, AgentTool[]>;
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
  toggleTool: (toolId: string, enabled: boolean) => Promise<void>;
  updateToolParams: (toolId: string, params: Record<string, string | number | boolean>) => Promise<void>;
  resetTool: (toolId: string) => Promise<void>;
  resetAllTools: () => Promise<void>;
  getTool: (toolId: string) => AgentTool | undefined;
  refresh: () => Promise<void>;
}

// ============================================================================
// API Functions
// ============================================================================

const toolsApi = {
  getAll: async (): Promise<AgentTool[]> => {
    const response = await apiClient.get('/llm/tools');
    return response.data;
  },

  toggle: async (toolId: string, enabled: boolean): Promise<AgentTool> => {
    const response = await apiClient.patch(`/llm/tools/${toolId}`, { enabled });
    return response.data;
  },

  updateParams: async (toolId: string, params: Record<string, string | number | boolean>): Promise<AgentTool> => {
    const response = await apiClient.patch(`/llm/tools/${toolId}/params`, { params });
    return response.data;
  },

  reset: async (toolId: string): Promise<AgentTool> => {
    const response = await apiClient.post(`/llm/tools/${toolId}/reset`);
    return response.data;
  },

  resetAll: async (): Promise<void> => {
    await apiClient.post('/llm/tools/reset-all');
  },
};

// ============================================================================
// Hook Implementation
// ============================================================================

export function useAgentTools(options: UseAgentToolsOptions = {}): UseAgentToolsReturn {
  const { enabled = true } = options;
  const queryClient = useQueryClient();

  // Query for tools
  const {
    data: tools = [],
    isLoading,
    isError,
    error,
    refetch,
  } = useQuery({
    queryKey: ['agent-tools'],
    queryFn: toolsApi.getAll,
    enabled,
    staleTime: 60000, // 1 minute
  });

  // Toggle mutation
  const toggleMutation = useMutation({
    mutationFn: ({ toolId, enabled }: { toolId: string; enabled: boolean }) =>
      toolsApi.toggle(toolId, enabled),
    onMutate: async ({ toolId, enabled }) => {
      // Optimistic update
      await queryClient.cancelQueries({ queryKey: ['agent-tools'] });
      const previousTools = queryClient.getQueryData<AgentTool[]>(['agent-tools']);
      queryClient.setQueryData<AgentTool[]>(['agent-tools'], (old) =>
        old?.map((t) => (t.id === toolId ? { ...t, enabled } : t))
      );
      return { previousTools };
    },
    onError: (_err, _vars, context) => {
      // Rollback on error
      if (context?.previousTools) {
        queryClient.setQueryData(['agent-tools'], context.previousTools);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-tools'] });
    },
  });

  // Update params mutation
  const updateParamsMutation = useMutation({
    mutationFn: ({ toolId, params }: { toolId: string; params: Record<string, string | number | boolean> }) =>
      toolsApi.updateParams(toolId, params),
    onMutate: async ({ toolId, params }) => {
      await queryClient.cancelQueries({ queryKey: ['agent-tools'] });
      const previousTools = queryClient.getQueryData<AgentTool[]>(['agent-tools']);
      queryClient.setQueryData<AgentTool[]>(['agent-tools'], (old) =>
        old?.map((t) => (t.id === toolId ? { ...t, parameterValues: params } : t))
      );
      return { previousTools };
    },
    onError: (_err, _vars, context) => {
      if (context?.previousTools) {
        queryClient.setQueryData(['agent-tools'], context.previousTools);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-tools'] });
    },
  });

  // Reset tool mutation
  const resetMutation = useMutation({
    mutationFn: toolsApi.reset,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-tools'] });
    },
  });

  // Reset all mutation
  const resetAllMutation = useMutation({
    mutationFn: toolsApi.resetAll,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-tools'] });
    },
  });

  // Computed values
  const enabledTools = useMemo(() => tools.filter((t) => t.enabled), [tools]);

  const toolsByCategory = useMemo(() => {
    const grouped: Record<ToolCategory, AgentTool[]> = {
      analysis: [],
      trading: [],
      risk: [],
      data: [],
      utility: [],
    };
    tools.forEach((tool) => {
      if (grouped[tool.category]) {
        grouped[tool.category].push(tool);
      }
    });
    return grouped;
  }, [tools]);

  // Handlers
  const toggleTool = useCallback(async (toolId: string, enabled: boolean) => {
    await toggleMutation.mutateAsync({ toolId, enabled });
  }, [toggleMutation]);

  const updateToolParams = useCallback(async (toolId: string, params: Record<string, string | number | boolean>) => {
    await updateParamsMutation.mutateAsync({ toolId, params });
  }, [updateParamsMutation]);

  const resetTool = useCallback(async (toolId: string) => {
    await resetMutation.mutateAsync(toolId);
  }, [resetMutation]);

  const resetAllTools = useCallback(async () => {
    await resetAllMutation.mutateAsync();
  }, [resetAllMutation]);

  const getTool = useCallback((toolId: string): AgentTool | undefined => {
    return tools.find((t) => t.id === toolId);
  }, [tools]);

  const refresh = useCallback(async () => {
    await refetch();
  }, [refetch]);

  return {
    tools,
    enabledTools,
    toolsByCategory,
    isLoading,
    isError,
    error: error as Error | null,
    toggleTool,
    updateToolParams,
    resetTool,
    resetAllTools,
    getTool,
    refresh,
  };
}

export default useAgentTools;
