/**
 * usePortfolioGoals Hook
 * Handles portfolio goals CRUD operations and state management
 */

import { useCallback } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import type {
  PortfolioGoal,
  CreateGoalInput,
  GoalProgress,
} from '../../../services/portfolio.service';

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

export interface GoalStats {
  total: number;
  onTrack: number;
  atRisk: number;
  behind: number;
  totalTarget: number;
  totalCurrent: number;
  avgProgress: number;
}

export interface UpdateGoalInput {
  name?: string;
  targetAmount?: number;
  targetDate?: string;
  monthlyContribution?: number;
}

export interface UsePortfolioGoalsOptions {
  onCreateSuccess?: (goal: PortfolioGoal) => void;
  onUpdateSuccess?: (goal: PortfolioGoal) => void;
  onDeleteSuccess?: (goalId: string) => void;
  onError?: (error: Error) => void;
}

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

const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3080';

async function getGoals(portfolioId?: string): Promise<PortfolioGoal[]> {
  const url = portfolioId
    ? `${API_URL}/api/v1/portfolio/${portfolioId}/goals`
    : `${API_URL}/api/v1/portfolio/goals`;

  const response = await fetch(url, { credentials: 'include' });

  if (!response.ok) {
    throw new Error('Failed to fetch goals');
  }

  const data = await response.json();
  return data.data || data;
}

async function getGoal(goalId: string): Promise<PortfolioGoal> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/goals/${goalId}`, {
    credentials: 'include',
  });

  if (!response.ok) {
    throw new Error('Failed to fetch goal');
  }

  const data = await response.json();
  return data.data || data;
}

async function getGoalProgress(goalId: string): Promise<GoalProgress> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/goals/${goalId}/progress`,
    { credentials: 'include' }
  );

  if (!response.ok) {
    throw new Error('Failed to fetch goal progress');
  }

  const data = await response.json();
  return data.data || data;
}

async function createGoal(input: CreateGoalInput): Promise<PortfolioGoal> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/goals`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(input),
  });

  if (!response.ok) {
    throw new Error('Failed to create goal');
  }

  const data = await response.json();
  return data.data || data;
}

async function updateGoal(
  goalId: string,
  updates: UpdateGoalInput
): Promise<PortfolioGoal> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/goals/${goalId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(updates),
  });

  if (!response.ok) {
    throw new Error('Failed to update goal');
  }

  const data = await response.json();
  return data.data || data;
}

async function updateGoalProgress(
  goalId: string,
  currentAmount: number
): Promise<PortfolioGoal> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/goals/${goalId}/progress`,
    {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      body: JSON.stringify({ currentAmount }),
    }
  );

  if (!response.ok) {
    throw new Error('Failed to update goal progress');
  }

  const data = await response.json();
  return data.data || data;
}

async function deleteGoal(goalId: string): Promise<void> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/goals/${goalId}`, {
    method: 'DELETE',
    credentials: 'include',
  });

  if (!response.ok) {
    throw new Error('Failed to delete goal');
  }
}

// ============================================================================
// Hook
// ============================================================================

export function usePortfolioGoals(
  portfolioId?: string,
  options: UsePortfolioGoalsOptions = {}
) {
  const queryClient = useQueryClient();
  const queryKey = portfolioId
    ? ['goals', portfolioId]
    : ['goals', 'all'];

  // Fetch goals
  const goalsQuery = useQuery({
    queryKey,
    queryFn: () => getGoals(portfolioId),
    staleTime: 2 * 60 * 1000, // 2 minutes
  });

  // Create goal mutation
  const createMutation = useMutation({
    mutationFn: createGoal,
    onSuccess: (goal) => {
      queryClient.invalidateQueries({ queryKey: ['goals'] });
      options.onCreateSuccess?.(goal);
    },
    onError: (error: Error) => {
      options.onError?.(error);
    },
  });

  // Update goal mutation
  const updateMutation = useMutation({
    mutationFn: ({ goalId, updates }: { goalId: string; updates: UpdateGoalInput }) =>
      updateGoal(goalId, updates),
    onSuccess: (goal) => {
      queryClient.invalidateQueries({ queryKey: ['goals'] });
      queryClient.invalidateQueries({ queryKey: ['goal', goal.id] });
      options.onUpdateSuccess?.(goal);
    },
    onError: (error: Error) => {
      options.onError?.(error);
    },
  });

  // Update progress mutation
  const updateProgressMutation = useMutation({
    mutationFn: ({ goalId, currentAmount }: { goalId: string; currentAmount: number }) =>
      updateGoalProgress(goalId, currentAmount),
    onSuccess: (goal) => {
      queryClient.invalidateQueries({ queryKey: ['goals'] });
      queryClient.invalidateQueries({ queryKey: ['goal', goal.id] });
      options.onUpdateSuccess?.(goal);
    },
    onError: (error: Error) => {
      options.onError?.(error);
    },
  });

  // Delete goal mutation
  const deleteMutation = useMutation({
    mutationFn: deleteGoal,
    onSuccess: (_, goalId) => {
      queryClient.invalidateQueries({ queryKey: ['goals'] });
      options.onDeleteSuccess?.(goalId);
    },
    onError: (error: Error) => {
      options.onError?.(error);
    },
  });

  // Calculate stats from goals
  const calculateStats = useCallback((): GoalStats => {
    const goals = goalsQuery.data || [];
    const total = goals.length;
    const onTrack = goals.filter((g) => g.status === 'on_track').length;
    const atRisk = goals.filter((g) => g.status === 'at_risk').length;
    const behind = goals.filter((g) => g.status === 'behind').length;
    const totalTarget = goals.reduce((sum, g) => sum + g.targetAmount, 0);
    const totalCurrent = goals.reduce((sum, g) => sum + g.currentAmount, 0);
    const avgProgress = total > 0 ? (totalCurrent / totalTarget) * 100 : 0;

    return {
      total,
      onTrack,
      atRisk,
      behind,
      totalTarget,
      totalCurrent,
      avgProgress,
    };
  }, [goalsQuery.data]);

  // Get goal by ID
  const getGoalById = useCallback(
    (goalId: string) => {
      return goalsQuery.data?.find((g) => g.id === goalId);
    },
    [goalsQuery.data]
  );

  // Get goals by status
  const getGoalsByStatus = useCallback(
    (status: PortfolioGoal['status']) => {
      return goalsQuery.data?.filter((g) => g.status === status) || [];
    },
    [goalsQuery.data]
  );

  // Sort goals by target date
  const sortedByTargetDate = useCallback(() => {
    if (!goalsQuery.data) return [];
    return [...goalsQuery.data].sort(
      (a, b) => new Date(a.targetDate).getTime() - new Date(b.targetDate).getTime()
    );
  }, [goalsQuery.data]);

  // Sort goals by progress
  const sortedByProgress = useCallback(() => {
    if (!goalsQuery.data) return [];
    return [...goalsQuery.data].sort((a, b) => b.progress - a.progress);
  }, [goalsQuery.data]);

  return {
    // Data
    goals: goalsQuery.data || [],
    stats: calculateStats(),

    // Helper functions
    getGoalById,
    getGoalsByStatus,
    sortedByTargetDate,
    sortedByProgress,

    // Loading states
    isLoading: goalsQuery.isLoading,
    isCreating: createMutation.isPending,
    isUpdating: updateMutation.isPending || updateProgressMutation.isPending,
    isDeleting: deleteMutation.isPending,

    // Error states
    error: goalsQuery.error,
    createError: createMutation.error,
    updateError: updateMutation.error || updateProgressMutation.error,
    deleteError: deleteMutation.error,

    // Actions
    create: createMutation.mutate,
    createAsync: createMutation.mutateAsync,
    update: (goalId: string, updates: UpdateGoalInput) =>
      updateMutation.mutate({ goalId, updates }),
    updateAsync: (goalId: string, updates: UpdateGoalInput) =>
      updateMutation.mutateAsync({ goalId, updates }),
    updateProgress: (goalId: string, currentAmount: number) =>
      updateProgressMutation.mutate({ goalId, currentAmount }),
    updateProgressAsync: (goalId: string, currentAmount: number) =>
      updateProgressMutation.mutateAsync({ goalId, currentAmount }),
    remove: deleteMutation.mutate,
    removeAsync: deleteMutation.mutateAsync,

    // Refetch
    refetch: goalsQuery.refetch,
  };
}

// Single goal hook for detail views
export function useGoalDetail(goalId: string) {
  const goalQuery = useQuery({
    queryKey: ['goal', goalId],
    queryFn: () => getGoal(goalId),
    enabled: !!goalId,
    staleTime: 2 * 60 * 1000,
  });

  const progressQuery = useQuery({
    queryKey: ['goal', goalId, 'progress'],
    queryFn: () => getGoalProgress(goalId),
    enabled: !!goalId,
    staleTime: 60 * 1000,
  });

  return {
    goal: goalQuery.data,
    progress: progressQuery.data,
    isLoading: goalQuery.isLoading || progressQuery.isLoading,
    error: goalQuery.error || progressQuery.error,
    refetch: () => {
      goalQuery.refetch();
      progressQuery.refetch();
    },
  };
}

export default usePortfolioGoals;
