/**
 * FlagController - Feature Flags Controller
 *
 * REST endpoints for managing feature flags.
 * Supports CRUD operations and bulk operations.
 *
 * @module FeatureFlags
 */

import { Router, Request, Response } from 'express';
import { DataSource } from 'typeorm';
import { FlagService, FlagFilters } from '../services/flag.service';

export function createFlagController(dataSource: DataSource): Router {
  const router = Router();
  const service = new FlagService(dataSource);

  // ==================== LIST & SEARCH ====================

  /**
   * GET /
   * List all flags with filters and pagination
   */
  router.get('/', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      const filters: FlagFilters = {
        enabled: req.query.enabled === 'true' ? true : req.query.enabled === 'false' ? false : undefined,
        isActive: req.query.isActive === 'true' ? true : req.query.isActive === 'false' ? false : undefined,
        search: req.query.search as string,
        tags: req.query.tags ? (req.query.tags as string).split(',') : undefined,
      };

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

      // If tenant is provided, get flags with tenant-specific overrides
      if (tenantId) {
        const result = await service.findAllForTenant(tenantId, filters, pagination);
        res.json(result);
      } else {
        const result = await service.findAll(filters, pagination);
        res.json(result);
      }
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /statistics
   * Get flag statistics
   */
  router.get('/statistics', async (_req: Request, res: Response): Promise<void> => {
    try {
      const stats = await service.getStatistics();
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /search
   * Search flags for autocomplete
   */
  router.get('/search', async (req: Request, res: Response): Promise<void> => {
    try {
      const query = req.query.q as string;
      const limit = parseInt(req.query.limit as string) || 10;

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

      const flags = await service.search(query, limit);
      res.json(flags);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /active
   * Get all active flags
   */
  router.get('/active', async (_req: Request, res: Response): Promise<void> => {
    try {
      const flags = await service.findAllActive();
      res.json(flags);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /by-code/:code
   * Get flag by code
   */
  router.get('/by-code/:code', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (tenantId) {
        const flag = await service.findByCodeForTenant(req.params.code, tenantId);
        if (!flag) {
          res.status(404).json({ error: 'Flag not found' });
          return;
        }
        res.json(flag);
      } else {
        const flag = await service.findByCode(req.params.code);
        if (!flag) {
          res.status(404).json({ error: 'Flag not found' });
          return;
        }
        res.json(flag);
      }
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /:id
   * Get flag by ID
   */
  router.get('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      if (tenantId) {
        const flag = await service.findByIdForTenant(req.params.id, tenantId);
        if (!flag) {
          res.status(404).json({ error: 'Flag not found' });
          return;
        }
        res.json(flag);
      } else {
        const flag = await service.findById(req.params.id);
        if (!flag) {
          res.status(404).json({ error: 'Flag not found' });
          return;
        }
        res.json(flag);
      }
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== CREATE & UPDATE ====================

  /**
   * POST /
   * Create a new flag
   */
  router.post('/', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;

      const flag = await service.create(req.body, userId);
      res.status(201).json(flag);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PUT /:id
   * Update a flag
   */
  router.put('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;

      const flag = await service.update(req.params.id, req.body, userId);
      if (!flag) {
        res.status(404).json({ error: 'Flag not found' });
        return;
      }

      res.json(flag);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PATCH /:id/toggle
   * Toggle flag enabled status
   */
  router.patch('/:id/toggle', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;

      const flag = await service.toggle(req.params.id, userId);
      if (!flag) {
        res.status(404).json({ error: 'Flag not found' });
        return;
      }

      res.json(flag);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PATCH /:id/rollout
   * Update rollout percentage
   */
  router.patch('/:id/rollout', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;
      const { percentage } = req.body;

      if (percentage === undefined) {
        res.status(400).json({ error: 'Percentage is required' });
        return;
      }

      const flag = await service.updateRollout(req.params.id, percentage, userId);
      if (!flag) {
        res.status(404).json({ error: 'Flag not found' });
        return;
      }

      res.json(flag);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  // ==================== DELETE ====================

  /**
   * DELETE /:id
   * Soft delete a flag (set isActive = false)
   */
  router.delete('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;

      const deleted = await service.delete(req.params.id, userId);
      if (!deleted) {
        res.status(404).json({ error: 'Flag not found' });
        return;
      }

      res.status(204).send();
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * DELETE /:id/permanent
   * Hard delete a flag (permanent removal)
   * Use with caution - this cannot be undone
   */
  router.delete('/:id/permanent', async (req: Request, res: Response): Promise<void> => {
    try {
      const deleted = await service.hardDelete(req.params.id);
      if (!deleted) {
        res.status(404).json({ error: 'Flag not found' });
        return;
      }

      res.status(204).send();
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
