/**
 * useAgentMode Hook
 * Manages agent mode (proactive/reactive) and related configuration
 * OQI-007: LLM Strategy Agent - Agent Mode Hook
 */

import { useCallback, useMemo } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '../../../lib/apiClient';
import type {
  AgentMode,
  AgentModeConfig,
  TriggerCondition,
  ActivitySchedule,
} from '../components/AgentModeSelector';

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

interface UseAgentModeOptions {
  enabled?: boolean;
}

interface UseAgentModeReturn {
  config: AgentModeConfig;
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
  // Mode
  mode: AgentMode;
  isProactive: boolean;
  isReactive: boolean;
  setMode: (mode: AgentMode) => Promise<void>;
  // Triggers
  triggers: TriggerCondition[];
  enabledTriggers: TriggerCondition[];
  updateTrigger: (triggerId: string, updates: Partial<TriggerCondition>) => Promise<void>;
  addTrigger: (trigger: Omit<TriggerCondition, 'id'>) => Promise<void>;
  removeTrigger: (triggerId: string) => Promise<void>;
  // Schedules
  schedules: ActivitySchedule[];
  activeSchedules: ActivitySchedule[];
  updateSchedule: (scheduleId: string, updates: Partial<ActivitySchedule>) => Promise<void>;
  // Config
  updateConfig: (updates: Partial<AgentModeConfig>) => Promise<void>;
  resetConfig: () => Promise<void>;
  refresh: () => Promise<void>;
}

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

const modeApi = {
  getConfig: async (): Promise<AgentModeConfig> => {
    const response = await apiClient.get('/llm/agent/mode');
    return response.data;
  },

  setMode: async (mode: AgentMode): Promise<AgentModeConfig> => {
    const response = await apiClient.patch('/llm/agent/mode', { mode });
    return response.data;
  },

  updateTrigger: async (triggerId: string, updates: Partial<TriggerCondition>): Promise<TriggerCondition> => {
    const response = await apiClient.patch(`/llm/agent/triggers/${triggerId}`, updates);
    return response.data;
  },

  addTrigger: async (trigger: Omit<TriggerCondition, 'id'>): Promise<TriggerCondition> => {
    const response = await apiClient.post('/llm/agent/triggers', trigger);
    return response.data;
  },

  removeTrigger: async (triggerId: string): Promise<void> => {
    await apiClient.delete(`/llm/agent/triggers/${triggerId}`);
  },

  updateSchedule: async (scheduleId: string, updates: Partial<ActivitySchedule>): Promise<ActivitySchedule> => {
    const response = await apiClient.patch(`/llm/agent/schedules/${scheduleId}`, updates);
    return response.data;
  },

  updateConfig: async (updates: Partial<AgentModeConfig>): Promise<AgentModeConfig> => {
    const response = await apiClient.patch('/llm/agent/config', updates);
    return response.data;
  },

  resetConfig: async (): Promise<AgentModeConfig> => {
    const response = await apiClient.post('/llm/agent/config/reset');
    return response.data;
  },
};

// ============================================================================
// Default Config
// ============================================================================

const DEFAULT_CONFIG: AgentModeConfig = {
  mode: 'reactive',
  triggers: [],
  schedules: Array.from({ length: 7 }, (_, i) => ({
    id: String(i),
    dayOfWeek: i,
    startTime: '09:00',
    endTime: '17:00',
    enabled: i >= 1 && i <= 5,
  })),
  notifyOnAction: true,
  requireConfirmation: true,
  maxActionsPerHour: 5,
};

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

export function useAgentMode(options: UseAgentModeOptions = {}): UseAgentModeReturn {
  const { enabled = true } = options;
  const queryClient = useQueryClient();

  // Query for config
  const {
    data: config = DEFAULT_CONFIG,
    isLoading,
    isError,
    error,
    refetch,
  } = useQuery({
    queryKey: ['agent-mode-config'],
    queryFn: modeApi.getConfig,
    enabled,
    staleTime: 60000, // 1 minute
  });

  // Set mode mutation
  const setModeMutation = useMutation({
    mutationFn: modeApi.setMode,
    onMutate: async (newMode) => {
      await queryClient.cancelQueries({ queryKey: ['agent-mode-config'] });
      const previousConfig = queryClient.getQueryData<AgentModeConfig>(['agent-mode-config']);
      queryClient.setQueryData<AgentModeConfig>(['agent-mode-config'], (old) =>
        old ? { ...old, mode: newMode } : undefined
      );
      return { previousConfig };
    },
    onError: (_err, _vars, context) => {
      if (context?.previousConfig) {
        queryClient.setQueryData(['agent-mode-config'], context.previousConfig);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Update trigger mutation
  const updateTriggerMutation = useMutation({
    mutationFn: ({ triggerId, updates }: { triggerId: string; updates: Partial<TriggerCondition> }) =>
      modeApi.updateTrigger(triggerId, updates),
    onMutate: async ({ triggerId, updates }) => {
      await queryClient.cancelQueries({ queryKey: ['agent-mode-config'] });
      const previousConfig = queryClient.getQueryData<AgentModeConfig>(['agent-mode-config']);
      queryClient.setQueryData<AgentModeConfig>(['agent-mode-config'], (old) =>
        old
          ? {
              ...old,
              triggers: old.triggers.map((t) =>
                t.id === triggerId ? { ...t, ...updates } : t
              ),
            }
          : undefined
      );
      return { previousConfig };
    },
    onError: (_err, _vars, context) => {
      if (context?.previousConfig) {
        queryClient.setQueryData(['agent-mode-config'], context.previousConfig);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Add trigger mutation
  const addTriggerMutation = useMutation({
    mutationFn: modeApi.addTrigger,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Remove trigger mutation
  const removeTriggerMutation = useMutation({
    mutationFn: modeApi.removeTrigger,
    onMutate: async (triggerId) => {
      await queryClient.cancelQueries({ queryKey: ['agent-mode-config'] });
      const previousConfig = queryClient.getQueryData<AgentModeConfig>(['agent-mode-config']);
      queryClient.setQueryData<AgentModeConfig>(['agent-mode-config'], (old) =>
        old
          ? { ...old, triggers: old.triggers.filter((t) => t.id !== triggerId) }
          : undefined
      );
      return { previousConfig };
    },
    onError: (_err, _vars, context) => {
      if (context?.previousConfig) {
        queryClient.setQueryData(['agent-mode-config'], context.previousConfig);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Update schedule mutation
  const updateScheduleMutation = useMutation({
    mutationFn: ({ scheduleId, updates }: { scheduleId: string; updates: Partial<ActivitySchedule> }) =>
      modeApi.updateSchedule(scheduleId, updates),
    onMutate: async ({ scheduleId, updates }) => {
      await queryClient.cancelQueries({ queryKey: ['agent-mode-config'] });
      const previousConfig = queryClient.getQueryData<AgentModeConfig>(['agent-mode-config']);
      queryClient.setQueryData<AgentModeConfig>(['agent-mode-config'], (old) =>
        old
          ? {
              ...old,
              schedules: old.schedules.map((s) =>
                s.id === scheduleId ? { ...s, ...updates } : s
              ),
            }
          : undefined
      );
      return { previousConfig };
    },
    onError: (_err, _vars, context) => {
      if (context?.previousConfig) {
        queryClient.setQueryData(['agent-mode-config'], context.previousConfig);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Update config mutation
  const updateConfigMutation = useMutation({
    mutationFn: modeApi.updateConfig,
    onMutate: async (updates) => {
      await queryClient.cancelQueries({ queryKey: ['agent-mode-config'] });
      const previousConfig = queryClient.getQueryData<AgentModeConfig>(['agent-mode-config']);
      queryClient.setQueryData<AgentModeConfig>(['agent-mode-config'], (old) =>
        old ? { ...old, ...updates } : undefined
      );
      return { previousConfig };
    },
    onError: (_err, _vars, context) => {
      if (context?.previousConfig) {
        queryClient.setQueryData(['agent-mode-config'], context.previousConfig);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Reset config mutation
  const resetConfigMutation = useMutation({
    mutationFn: modeApi.resetConfig,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['agent-mode-config'] });
    },
  });

  // Computed values
  const enabledTriggers = useMemo(() =>
    config.triggers.filter((t) => t.enabled),
    [config.triggers]
  );

  const activeSchedules = useMemo(() =>
    config.schedules.filter((s) => s.enabled),
    [config.schedules]
  );

  // Handlers
  const setMode = useCallback(async (mode: AgentMode) => {
    await setModeMutation.mutateAsync(mode);
  }, [setModeMutation]);

  const updateTrigger = useCallback(async (triggerId: string, updates: Partial<TriggerCondition>) => {
    await updateTriggerMutation.mutateAsync({ triggerId, updates });
  }, [updateTriggerMutation]);

  const addTrigger = useCallback(async (trigger: Omit<TriggerCondition, 'id'>) => {
    await addTriggerMutation.mutateAsync(trigger);
  }, [addTriggerMutation]);

  const removeTrigger = useCallback(async (triggerId: string) => {
    await removeTriggerMutation.mutateAsync(triggerId);
  }, [removeTriggerMutation]);

  const updateSchedule = useCallback(async (scheduleId: string, updates: Partial<ActivitySchedule>) => {
    await updateScheduleMutation.mutateAsync({ scheduleId, updates });
  }, [updateScheduleMutation]);

  const updateConfig = useCallback(async (updates: Partial<AgentModeConfig>) => {
    await updateConfigMutation.mutateAsync(updates);
  }, [updateConfigMutation]);

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

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

  return {
    config,
    isLoading,
    isError,
    error: error as Error | null,
    mode: config.mode,
    isProactive: config.mode === 'proactive',
    isReactive: config.mode === 'reactive',
    setMode,
    triggers: config.triggers,
    enabledTriggers,
    updateTrigger,
    addTrigger,
    removeTrigger,
    schedules: config.schedules,
    activeSchedules,
    updateSchedule,
    updateConfig,
    resetConfig,
    refresh,
  };
}

export default useAgentMode;
