/**
 * FlagEvaluationController - Feature Flag Evaluation Controller
 *
 * REST endpoints for evaluating feature flags.
 * Supports single flag evaluation, bulk evaluation, and analytics.
 *
 * @module FeatureFlags
 */

import { Router, Request, Response } from 'express';
import { DataSource } from 'typeorm';
import { FlagEvaluationService, EvaluationContext, EvaluationFilters } from '../services/flag-evaluation.service';

export function createFlagEvaluationController(dataSource: DataSource): Router {
  const router = Router();
  const service = new FlagEvaluationService(dataSource);

  // ==================== EVALUATION ENDPOINTS ====================

  /**
   * POST /evaluate
   * Evaluate a single flag for a tenant
   * Body: { flagCode: string, context?: EvaluationContext, track?: boolean }
   */
  router.post('/evaluate', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (!tenantId) {
        res.status(400).json({ error: 'x-tenant-id header is required' });
        return;
      }

      const { flagCode, context = {}, track = true } = req.body;

      if (!flagCode) {
        res.status(400).json({ error: 'flagCode is required' });
        return;
      }

      // Add user info from request if available
      const evaluationContext: EvaluationContext = {
        ...context,
        userId: context.userId || (req as any).user?.id,
        userEmail: context.userEmail || (req as any).user?.email,
        userRole: context.userRole || (req as any).user?.role,
      };

      const result = await service.evaluate(flagCode, tenantId, evaluationContext, track);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /evaluate-bulk
   * Evaluate multiple flags at once
   * Body: { flagCodes: string[], context?: EvaluationContext, track?: boolean }
   */
  router.post('/evaluate-bulk', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (!tenantId) {
        res.status(400).json({ error: 'x-tenant-id header is required' });
        return;
      }

      const { flagCodes, context = {}, track = true } = req.body;

      if (!flagCodes || !Array.isArray(flagCodes) || flagCodes.length === 0) {
        res.status(400).json({ error: 'flagCodes array is required and must not be empty' });
        return;
      }

      const evaluationContext: EvaluationContext = {
        ...context,
        userId: context.userId || (req as any).user?.id,
        userEmail: context.userEmail || (req as any).user?.email,
        userRole: context.userRole || (req as any).user?.role,
      };

      const result = await service.evaluateBulk(flagCodes, tenantId, evaluationContext, track);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /evaluate-all
   * Evaluate all active flags for a tenant
   * Body: { context?: EvaluationContext, track?: boolean }
   */
  router.post('/evaluate-all', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (!tenantId) {
        res.status(400).json({ error: 'x-tenant-id header is required' });
        return;
      }

      const { context = {}, track = true } = req.body;

      const evaluationContext: EvaluationContext = {
        ...context,
        userId: context.userId || (req as any).user?.id,
        userEmail: context.userEmail || (req as any).user?.email,
        userRole: context.userRole || (req as any).user?.role,
      };

      const result = await service.evaluateAll(tenantId, evaluationContext, track);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /check/:flagCode
   * Quick check if a flag is enabled (no tracking)
   * Returns: { enabled: boolean }
   */
  router.get('/check/:flagCode', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (!tenantId) {
        res.status(400).json({ error: 'x-tenant-id header is required' });
        return;
      }

      const userId = (req as any).user?.id || (req.query.userId as string);

      const enabled = await service.isEnabled(req.params.flagCode, tenantId, userId);
      res.json({ enabled });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /rollout-bucket/:flagCode
   * Get the rollout bucket for debugging purposes
   * Returns: { bucket: number, percentage: number, isIncluded: boolean }
   */
  router.get('/rollout-bucket/:flagCode', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (!tenantId) {
        res.status(400).json({ error: 'x-tenant-id header is required' });
        return;
      }

      const userId = (req as any).user?.id || (req.query.userId as string);

      const bucket = service.getRolloutBucket(req.params.flagCode, tenantId, userId);

      res.json({
        flagCode: req.params.flagCode,
        tenantId,
        userId,
        bucket,
        description: `User is in bucket ${bucket} (0-99)`,
      });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== HISTORY & ANALYTICS ====================

  /**
   * GET /history
   * Get evaluation history with filters
   */
  router.get('/history', async (req: Request, res: Response): Promise<void> => {
    try {
      const filters: EvaluationFilters = {
        flagId: req.query.flagId as string,
        tenantId: req.query.tenantId as string,
        userId: req.query.userId as string,
        result: req.query.result === 'true' ? true : req.query.result === 'false' ? false : undefined,
        startDate: req.query.startDate ? new Date(req.query.startDate as string) : undefined,
        endDate: req.query.endDate ? new Date(req.query.endDate as string) : undefined,
      };

      const pagination = {
        page: parseInt(req.query.page as string) || 1,
        limit: parseInt(req.query.limit as string) || 50,
      };

      const result = await service.getEvaluationHistory(filters, pagination);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /stats/:flagId
   * Get evaluation statistics for a flag
   */
  router.get('/stats/:flagId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.query.tenantId as string;
      const days = parseInt(req.query.days as string) || 7;

      const stats = await service.getEvaluationStats(req.params.flagId, tenantId, days);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== MAINTENANCE ====================

  /**
   * POST /cleanup
   * Clean up old evaluation records
   * Body: { daysToKeep?: number }
   */
  router.post('/cleanup', async (req: Request, res: Response): Promise<void> => {
    try {
      const { daysToKeep = 30 } = req.body;

      const deleted = await service.cleanupOldEvaluations(daysToKeep);
      res.json({
        success: true,
        deleted,
        message: `Deleted ${deleted} evaluation records older than ${daysToKeep} days`,
      });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
