/**
 * Portfolio Controller
 * Handles portfolio management endpoints
 */

import { Request, Response, NextFunction } from 'express';
import { portfolioService, RiskProfile } from '../services/portfolio.service';

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

// Use Request directly - user is already declared globally in auth.middleware.ts
type AuthRequest = Request;

// ============================================================================
// Portfolio Management
// ============================================================================

/**
 * Create a new portfolio
 */
export async function createPortfolio(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { name, riskProfile, initialValue } = req.body;

    if (!name || !riskProfile) {
      res.status(400).json({
        success: false,
        error: { message: 'Name and risk profile are required', code: 'VALIDATION_ERROR' },
      });
      return;
    }

    const validProfiles: RiskProfile[] = ['conservative', 'moderate', 'aggressive'];
    if (!validProfiles.includes(riskProfile)) {
      res.status(400).json({
        success: false,
        error: { message: 'Invalid risk profile', code: 'VALIDATION_ERROR' },
      });
      return;
    }

    const portfolio = await portfolioService.createPortfolio(
      userId,
      name,
      riskProfile,
      initialValue || 0
    );

    res.status(201).json({
      success: true,
      data: portfolio,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Get user's portfolios
 */
export async function getPortfolios(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const portfolios = await portfolioService.getUserPortfolios(userId);

    res.json({
      success: true,
      data: portfolios,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Get portfolio by ID
 */
export async function getPortfolio(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { portfolioId } = req.params;

    const portfolio = await portfolioService.getPortfolio(portfolioId);
    if (!portfolio) {
      res.status(404).json({
        success: false,
        error: { message: 'Portfolio not found', code: 'NOT_FOUND' },
      });
      return;
    }

    if (portfolio.userId !== userId) {
      res.status(403).json({
        success: false,
        error: { message: 'Forbidden', code: 'FORBIDDEN' },
      });
      return;
    }

    res.json({
      success: true,
      data: portfolio,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Update portfolio allocations
 */
export async function updateAllocations(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { portfolioId } = req.params;
    const { allocations } = req.body;

    if (!allocations || !Array.isArray(allocations)) {
      res.status(400).json({
        success: false,
        error: { message: 'Allocations array is required', code: 'VALIDATION_ERROR' },
      });
      return;
    }

    const portfolio = await portfolioService.getPortfolio(portfolioId);
    if (!portfolio) {
      res.status(404).json({
        success: false,
        error: { message: 'Portfolio not found', code: 'NOT_FOUND' },
      });
      return;
    }

    if (portfolio.userId !== userId) {
      res.status(403).json({
        success: false,
        error: { message: 'Forbidden', code: 'FORBIDDEN' },
      });
      return;
    }

    const updated = await portfolioService.updateAllocations(portfolioId, allocations);

    res.json({
      success: true,
      data: updated,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Get rebalancing recommendations
 */
export async function getRebalanceRecommendations(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { portfolioId } = req.params;

    const portfolio = await portfolioService.getPortfolio(portfolioId);
    if (!portfolio) {
      res.status(404).json({
        success: false,
        error: { message: 'Portfolio not found', code: 'NOT_FOUND' },
      });
      return;
    }

    if (portfolio.userId !== userId) {
      res.status(403).json({
        success: false,
        error: { message: 'Forbidden', code: 'FORBIDDEN' },
      });
      return;
    }

    const recommendations = await portfolioService.getRebalanceRecommendations(portfolioId);

    res.json({
      success: true,
      data: recommendations,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Execute rebalancing
 */
export async function executeRebalance(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { portfolioId } = req.params;

    const portfolio = await portfolioService.getPortfolio(portfolioId);
    if (!portfolio) {
      res.status(404).json({
        success: false,
        error: { message: 'Portfolio not found', code: 'NOT_FOUND' },
      });
      return;
    }

    if (portfolio.userId !== userId) {
      res.status(403).json({
        success: false,
        error: { message: 'Forbidden', code: 'FORBIDDEN' },
      });
      return;
    }

    const rebalanced = await portfolioService.executeRebalance(portfolioId);

    res.json({
      success: true,
      data: rebalanced,
      message: 'Portfolio rebalanced successfully',
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Get portfolio statistics
 */
export async function getPortfolioStats(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { portfolioId } = req.params;

    const portfolio = await portfolioService.getPortfolio(portfolioId);
    if (!portfolio) {
      res.status(404).json({
        success: false,
        error: { message: 'Portfolio not found', code: 'NOT_FOUND' },
      });
      return;
    }

    if (portfolio.userId !== userId) {
      res.status(403).json({
        success: false,
        error: { message: 'Forbidden', code: 'FORBIDDEN' },
      });
      return;
    }

    const stats = await portfolioService.getPortfolioStats(portfolioId);

    res.json({
      success: true,
      data: stats,
    });
  } catch (error) {
    next(error);
  }
}

// ============================================================================
// Goal Management
// ============================================================================

/**
 * Create a financial goal
 */
export async function createGoal(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { name, targetAmount, targetDate, monthlyContribution } = req.body;

    if (!name || !targetAmount || !targetDate || !monthlyContribution) {
      res.status(400).json({
        success: false,
        error: { message: 'All fields are required', code: 'VALIDATION_ERROR' },
      });
      return;
    }

    const goal = await portfolioService.createGoal(
      userId,
      name,
      Number(targetAmount),
      new Date(targetDate),
      Number(monthlyContribution)
    );

    res.status(201).json({
      success: true,
      data: goal,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Get user's goals
 */
export async function getGoals(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const goals = await portfolioService.getUserGoals(userId);

    res.json({
      success: true,
      data: goals,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Update goal progress
 */
export async function updateGoalProgress(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { goalId } = req.params;
    const { currentAmount } = req.body;

    if (currentAmount === undefined) {
      res.status(400).json({
        success: false,
        error: { message: 'Current amount is required', code: 'VALIDATION_ERROR' },
      });
      return;
    }

    const goal = await portfolioService.updateGoalProgress(goalId, Number(currentAmount));

    res.json({
      success: true,
      data: goal,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * Delete a goal
 */
export async function deleteGoal(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
  try {
    const userId = req.user?.id;
    if (!userId) {
      res.status(401).json({
        success: false,
        error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
      });
      return;
    }

    const { goalId } = req.params;

    const deleted = await portfolioService.deleteGoal(goalId);
    if (!deleted) {
      res.status(404).json({
        success: false,
        error: { message: 'Goal not found', code: 'NOT_FOUND' },
      });
      return;
    }

    res.json({
      success: true,
      message: 'Goal deleted',
    });
  } catch (error) {
    next(error);
  }
}
