/**
 * useRiskMetrics Hook
 * Handles portfolio risk metrics and analysis
 */

import { useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import type {
  PortfolioMetrics,
  PortfolioAllocation,
} from '../../../services/portfolio.service';

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

export type RiskLevel = 'low' | 'moderate' | 'high' | 'very-high';

export interface RiskRating {
  level: RiskLevel;
  score: number;
  label: string;
  color: string;
  bgColor: string;
}

export interface DrawdownPeriod {
  startDate: string;
  endDate: string;
  duration: number;
  peakValue: number;
  troughValue: number;
  drawdownPercent: number;
  recovered: boolean;
}

export interface RiskContribution {
  asset: string;
  weight: number;
  volatility: number;
  contribution: number;
  contributionPercent: number;
}

export interface StressTestScenario {
  name: string;
  description: string;
  impact: number;
  impactPercent: number;
}

export interface CorrelationPair {
  asset1: string;
  asset2: string;
  correlation: number;
}

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

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

async function getPortfolioMetrics(portfolioId: string): Promise<PortfolioMetrics> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/${portfolioId}/metrics`,
    { credentials: 'include' }
  );

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

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

async function getDrawdownHistory(portfolioId: string): Promise<DrawdownPeriod[]> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/${portfolioId}/drawdowns`,
    { credentials: 'include' }
  );

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

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

async function getRiskContributions(
  portfolioId: string
): Promise<RiskContribution[]> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/${portfolioId}/risk-contributions`,
    { credentials: 'include' }
  );

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

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

async function getStressTests(portfolioId: string): Promise<StressTestScenario[]> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/${portfolioId}/stress-tests`,
    { credentials: 'include' }
  );

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

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

async function getCorrelationMatrix(
  portfolioId: string
): Promise<{ assets: string[]; matrix: number[][] }> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/${portfolioId}/correlations`,
    { credentials: 'include' }
  );

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

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

// ============================================================================
// Helper Functions
// ============================================================================

function calculateRiskRating(metrics: PortfolioMetrics | null): RiskRating {
  if (!metrics) {
    return {
      level: 'moderate',
      score: 50,
      label: 'Moderado',
      color: 'text-yellow-500',
      bgColor: 'bg-yellow-100 dark:bg-yellow-900/30',
    };
  }

  let score = 50;

  // Volatility impact
  if (metrics.volatility > 30) score += 20;
  else if (metrics.volatility > 20) score += 10;
  else if (metrics.volatility < 10) score -= 15;

  // Sharpe ratio impact
  if (metrics.sharpeRatio > 2) score -= 20;
  else if (metrics.sharpeRatio > 1) score -= 10;
  else if (metrics.sharpeRatio < 0.5) score += 15;

  // Max drawdown impact
  const absDrawdown = Math.abs(metrics.maxDrawdownPercent);
  if (absDrawdown > 25) score += 20;
  else if (absDrawdown > 15) score += 10;
  else if (absDrawdown < 5) score -= 10;

  // Beta impact
  if (metrics.beta > 1.5) score += 15;
  else if (metrics.beta > 1.2) score += 5;
  else if (metrics.beta < 0.8) score -= 10;

  score = Math.max(0, Math.min(100, score));

  if (score >= 70) {
    return {
      level: 'very-high',
      score,
      label: 'Muy Alto',
      color: 'text-red-600',
      bgColor: 'bg-red-100 dark:bg-red-900/30',
    };
  } else if (score >= 50) {
    return {
      level: 'high',
      score,
      label: 'Alto',
      color: 'text-orange-500',
      bgColor: 'bg-orange-100 dark:bg-orange-900/30',
    };
  } else if (score >= 30) {
    return {
      level: 'moderate',
      score,
      label: 'Moderado',
      color: 'text-yellow-500',
      bgColor: 'bg-yellow-100 dark:bg-yellow-900/30',
    };
  } else {
    return {
      level: 'low',
      score,
      label: 'Bajo',
      color: 'text-green-500',
      bgColor: 'bg-green-100 dark:bg-green-900/30',
    };
  }
}

function getHighCorrelationPairs(
  assets: string[],
  matrix: number[][],
  threshold: number = 0.7
): CorrelationPair[] {
  const pairs: CorrelationPair[] = [];

  for (let i = 0; i < matrix.length; i++) {
    for (let j = i + 1; j < matrix.length; j++) {
      if (matrix[i][j] >= threshold) {
        pairs.push({
          asset1: assets[i],
          asset2: assets[j],
          correlation: matrix[i][j],
        });
      }
    }
  }

  return pairs.sort((a, b) => b.correlation - a.correlation);
}

function calculateDiversificationScore(matrix: number[][]): number {
  if (matrix.length < 2) return 100;

  let totalCorr = 0;
  let count = 0;

  for (let i = 0; i < matrix.length; i++) {
    for (let j = i + 1; j < matrix.length; j++) {
      totalCorr += matrix[i][j];
      count++;
    }
  }

  const avgCorr = count > 0 ? totalCorr / count : 0;
  return Math.max(0, Math.min(100, (1 - avgCorr) * 100));
}

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

export function useRiskMetrics(portfolioId: string) {
  // Fetch metrics
  const metricsQuery = useQuery({
    queryKey: ['portfolio', portfolioId, 'metrics'],
    queryFn: () => getPortfolioMetrics(portfolioId),
    enabled: !!portfolioId,
    staleTime: 5 * 60 * 1000, // 5 minutes
  });

  // Fetch drawdowns
  const drawdownsQuery = useQuery({
    queryKey: ['portfolio', portfolioId, 'drawdowns'],
    queryFn: () => getDrawdownHistory(portfolioId),
    enabled: !!portfolioId,
    staleTime: 10 * 60 * 1000, // 10 minutes
  });

  // Fetch risk contributions
  const contributionsQuery = useQuery({
    queryKey: ['portfolio', portfolioId, 'risk-contributions'],
    queryFn: () => getRiskContributions(portfolioId),
    enabled: !!portfolioId,
    staleTime: 5 * 60 * 1000,
  });

  // Fetch stress tests
  const stressTestsQuery = useQuery({
    queryKey: ['portfolio', portfolioId, 'stress-tests'],
    queryFn: () => getStressTests(portfolioId),
    enabled: !!portfolioId,
    staleTime: 30 * 60 * 1000, // 30 minutes
  });

  // Fetch correlations
  const correlationsQuery = useQuery({
    queryKey: ['portfolio', portfolioId, 'correlations'],
    queryFn: () => getCorrelationMatrix(portfolioId),
    enabled: !!portfolioId,
    staleTime: 30 * 60 * 1000,
  });

  // Calculate risk rating
  const riskRating = useMemo(
    () => calculateRiskRating(metricsQuery.data || null),
    [metricsQuery.data]
  );

  // Calculate diversification score
  const diversificationScore = useMemo(() => {
    if (!correlationsQuery.data?.matrix) return 0;
    return calculateDiversificationScore(correlationsQuery.data.matrix);
  }, [correlationsQuery.data]);

  // Get high correlation pairs
  const highCorrelationPairs = useMemo(() => {
    if (!correlationsQuery.data) return [];
    return getHighCorrelationPairs(
      correlationsQuery.data.assets,
      correlationsQuery.data.matrix
    );
  }, [correlationsQuery.data]);

  // Get worst drawdown
  const worstDrawdown = useMemo(() => {
    if (!drawdownsQuery.data?.length) return null;
    return drawdownsQuery.data.reduce((worst, current) =>
      current.drawdownPercent < worst.drawdownPercent ? current : worst
    );
  }, [drawdownsQuery.data]);

  // Get top risk contributors
  const topRiskContributors = useMemo(() => {
    if (!contributionsQuery.data) return [];
    return [...contributionsQuery.data]
      .sort((a, b) => b.contributionPercent - a.contributionPercent)
      .slice(0, 5);
  }, [contributionsQuery.data]);

  return {
    // Data
    metrics: metricsQuery.data,
    drawdowns: drawdownsQuery.data || [],
    contributions: contributionsQuery.data || [],
    stressTests: stressTestsQuery.data || [],
    correlations: correlationsQuery.data,

    // Computed values
    riskRating,
    diversificationScore,
    highCorrelationPairs,
    worstDrawdown,
    topRiskContributors,

    // Loading states
    isLoading:
      metricsQuery.isLoading ||
      drawdownsQuery.isLoading ||
      contributionsQuery.isLoading,
    isLoadingStressTests: stressTestsQuery.isLoading,
    isLoadingCorrelations: correlationsQuery.isLoading,

    // Error states
    error:
      metricsQuery.error ||
      drawdownsQuery.error ||
      contributionsQuery.error,
    stressTestsError: stressTestsQuery.error,
    correlationsError: correlationsQuery.error,

    // Refetch
    refetchMetrics: metricsQuery.refetch,
    refetchDrawdowns: drawdownsQuery.refetch,
    refetchContributions: contributionsQuery.refetch,
    refetchStressTests: stressTestsQuery.refetch,
    refetchCorrelations: correlationsQuery.refetch,
    refetchAll: () => {
      metricsQuery.refetch();
      drawdownsQuery.refetch();
      contributionsQuery.refetch();
      stressTestsQuery.refetch();
      correlationsQuery.refetch();
    },
  };
}

export default useRiskMetrics;
