/**
 * Portfolio Service
 * Client for connecting to the Portfolio API
 */

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

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

export type RiskProfile = 'conservative' | 'moderate' | 'aggressive';

export interface Portfolio {
  id: string;
  userId: string;
  name: string;
  riskProfile: RiskProfile;
  allocations: PortfolioAllocation[];
  totalValue: number;
  totalCost: number;
  unrealizedPnl: number;
  unrealizedPnlPercent: number;
  realizedPnl: number;
  lastRebalanced: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface PortfolioAllocation {
  id: string;
  portfolioId: string;
  asset: string;
  targetPercent: number;
  currentPercent: number;
  quantity: number;
  value: number;
  cost: number;
  pnl: number;
  pnlPercent: number;
  deviation: number;
}

export interface PortfolioGoal {
  id: string;
  userId: string;
  name: string;
  targetAmount: number;
  currentAmount: number;
  targetDate: string;
  monthlyContribution: number;
  progress: number;
  projectedCompletion: string | null;
  status: 'on_track' | 'at_risk' | 'behind';
  createdAt: string;
  updatedAt: string;
}

export interface RebalanceRecommendation {
  asset: string;
  currentPercent: number;
  targetPercent: number;
  action: 'buy' | 'sell' | 'hold';
  amount: number;
  amountUSD: number;
  priority: 'high' | 'medium' | 'low';
}

export interface PortfolioStats {
  totalValue: number;
  dayChange: number;
  dayChangePercent: number;
  weekChange: number;
  weekChangePercent: number;
  monthChange: number;
  monthChangePercent: number;
  allTimeChange: number;
  allTimeChangePercent: number;
  bestPerformer: { asset: string; change: number };
  worstPerformer: { asset: string; change: number };
}

export interface CreatePortfolioInput {
  name: string;
  riskProfile: RiskProfile;
  initialValue?: number;
}

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

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

/**
 * Get user's portfolios
 */
export async function getUserPortfolios(): Promise<Portfolio[]> {
  const response = await fetch(`${API_URL}/api/v1/portfolio`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to fetch portfolios');
  const data = await response.json();
  return data.data || data;
}

/**
 * Get portfolio by ID
 */
export async function getPortfolio(portfolioId: string): Promise<Portfolio> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to fetch portfolio');
  const data = await response.json();
  return data.data || data;
}

/**
 * Create a new portfolio
 */
export async function createPortfolio(input: CreatePortfolioInput): Promise<Portfolio> {
  const response = await fetch(`${API_URL}/api/v1/portfolio`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(input),
  });
  if (!response.ok) throw new Error('Failed to create portfolio');
  const data = await response.json();
  return data.data || data;
}

/**
 * Update portfolio allocations
 */
export async function updateAllocations(
  portfolioId: string,
  allocations: { asset: string; targetPercent: number }[]
): Promise<Portfolio> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/allocations`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify({ allocations }),
  });
  if (!response.ok) throw new Error('Failed to update allocations');
  const data = await response.json();
  return data.data || data;
}

/**
 * Get rebalancing recommendations
 */
export async function getRebalanceRecommendations(
  portfolioId: string
): Promise<RebalanceRecommendation[]> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/rebalance`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to fetch recommendations');
  const data = await response.json();
  return data.data || data;
}

/**
 * Execute rebalancing
 */
export async function executeRebalance(portfolioId: string): Promise<Portfolio> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/rebalance`, {
    method: 'POST',
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to execute rebalance');
  const data = await response.json();
  return data.data || data;
}

/**
 * Get portfolio statistics
 */
export async function getPortfolioStats(portfolioId: string): Promise<PortfolioStats> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/stats`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to fetch stats');
  const data = await response.json();
  return data.data || data;
}

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

export interface PerformanceDataPoint {
  date: string;
  value: number;
  pnl: number;
  pnlPercent: number;
  change: number;
  changePercent: number;
}

export interface PerformanceStats {
  dayChange: number;
  dayChangePercent: number;
  weekChange: number;
  weekChangePercent: number;
  monthChange: number;
  monthChangePercent: number;
  yearChange: number;
  yearChangePercent: number;
  allTimeChange: number;
  allTimeChangePercent: number;
}

export type PerformancePeriod = 'week' | 'month' | '3months' | 'year' | 'all';

/**
 * Get portfolio performance history for charts
 */
export async function getPortfolioPerformance(
  portfolioId: string,
  period: PerformancePeriod = 'month'
): Promise<PerformanceDataPoint[]> {
  const response = await fetch(
    `${API_URL}/api/v1/portfolio/${portfolioId}/performance?period=${period}`,
    { credentials: 'include' }
  );
  if (!response.ok) throw new Error('Failed to fetch performance');
  const data = await response.json();
  return data.data || data;
}

/**
 * Get detailed performance statistics
 */
export async function getPerformanceStats(portfolioId: string): Promise<PerformanceStats> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/performance/stats`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to fetch performance stats');
  const data = await response.json();
  return data.data || data;
}

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

/**
 * Get user's goals
 */
export async function getUserGoals(): Promise<PortfolioGoal[]> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/goals`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to fetch goals');
  const data = await response.json();
  return data.data || data;
}

/**
 * Create a new goal
 */
export 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;
}

/**
 * Update goal progress
 */
export 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');
  const data = await response.json();
  return data.data || data;
}

/**
 * Delete a goal
 */
export 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');
}

/**
 * Get goal progress details
 */
export 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;
}

// ============================================================================
// Portfolio Metrics API Functions
// ============================================================================

export interface PortfolioMetrics {
  totalReturn: number;
  totalReturnPercent: number;
  annualizedReturn: number;
  annualizedReturnPercent: number;
  volatility: number;
  sharpeRatio: number;
  sortinoRatio: number;
  maxDrawdown: number;
  maxDrawdownPercent: number;
  maxDrawdownDate: string | null;
  beta: number;
  alpha: number;
  rSquared: number;
  trackingError: number;
  informationRatio: number;
  calmarRatio: number;
  updatedAt: string;
}

export interface GoalProgress {
  goalId: string;
  name: string;
  currentAmount: number;
  targetAmount: number;
  progress: number;
  monthlyContribution: number;
  monthsRemaining: number;
  projectedCompletion: string | null;
  status: 'on_track' | 'at_risk' | 'behind';
  requiredMonthlyRate: number;
  onTrackPercentage: number;
  milestones: GoalMilestone[];
}

export interface GoalMilestone {
  percent: number;
  amount: number;
  date: string;
  achieved: boolean;
}

export interface RebalanceCalculation {
  portfolioId: string;
  currentValue: number;
  trades: RebalanceTrade[];
  estimatedCost: number;
  estimatedFees: number;
  totalTrades: number;
  netChange: number;
  summary: RebalanceSummary;
}

export interface RebalanceTrade {
  asset: string;
  action: 'buy' | 'sell';
  quantity: number;
  estimatedPrice: number;
  estimatedValue: number;
  currentPercent: number;
  targetPercent: number;
  deviation: number;
  priority: 'high' | 'medium' | 'low';
}

export interface RebalanceSummary {
  totalBuy: number;
  totalSell: number;
  netFlow: number;
  assetsToAdjust: number;
  maxDeviation: number;
  averageDeviation: number;
}

/**
 * Get detailed portfolio metrics
 */
export 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;
}

/**
 * Calculate rebalance trades without executing
 */
export async function calculateRebalance(portfolioId: string): Promise<RebalanceCalculation> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/rebalance/calculate`, {
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to calculate rebalance');
  const data = await response.json();
  return data.data || data;
}

/**
 * Update portfolio settings
 */
export async function updatePortfolio(
  portfolioId: string,
  updates: Partial<Pick<Portfolio, 'name' | 'riskProfile'>>
): Promise<Portfolio> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(updates),
  });
  if (!response.ok) throw new Error('Failed to update portfolio');
  const data = await response.json();
  return data.data || data;
}

/**
 * Delete a portfolio
 */
export async function deletePortfolio(portfolioId: string): Promise<void> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}`, {
    method: 'DELETE',
    credentials: 'include',
  });
  if (!response.ok) throw new Error('Failed to delete portfolio');
}

/**
 * Add position to portfolio
 */
export async function addPosition(
  portfolioId: string,
  position: { asset: string; quantity: number; cost: number }
): Promise<Portfolio> {
  const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/positions`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(position),
  });
  if (!response.ok) throw new Error('Failed to add position');
  const data = await response.json();
  return data.data || data;
}
