/**
 * TenantOverrideController - Tenant Override Controller
 *
 * REST endpoints for managing per-tenant feature flag overrides.
 * Allows enabling/disabling flags for specific tenants.
 *
 * @module FeatureFlags
 */

import { Router, Request, Response } from 'express';
import { DataSource } from 'typeorm';
import { TenantOverrideService, OverrideFilters } from '../services/tenant-override.service';

export function createTenantOverrideController(dataSource: DataSource): Router {
  const router = Router();
  const service = new TenantOverrideService(dataSource);

  // ==================== LIST & GET ====================

  /**
   * GET /
   * List all overrides with filters and pagination
   */
  router.get('/', async (req: Request, res: Response): Promise<void> => {
    try {
      const filters: OverrideFilters = {
        tenantId: req.query.tenantId as string,
        flagId: req.query.flagId as string,
        enabled: req.query.enabled === 'true' ? true : req.query.enabled === 'false' ? false : undefined,
        expired: req.query.expired === 'true' ? true : req.query.expired === 'false' ? false : undefined,
        expiresSoon: req.query.expiresSoon === 'true',
      };

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

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

  /**
   * GET /statistics
   * Get override 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 /expiring-soon
   * Get overrides expiring soon
   */
  router.get('/expiring-soon', async (req: Request, res: Response): Promise<void> => {
    try {
      const days = parseInt(req.query.days as string) || 7;
      const overrides = await service.getExpiringSoon(days);
      res.json(overrides);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * GET /tenant/:tenantId
   * Get all overrides for a tenant
   */
  router.get('/tenant/:tenantId', async (req: Request, res: Response): Promise<void> => {
    try {
      const overrides = await service.findByTenant(req.params.tenantId);
      res.json(overrides);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /tenant/:tenantId/count
   * Get override count for a tenant
   */
  router.get('/tenant/:tenantId/count', async (req: Request, res: Response): Promise<void> => {
    try {
      const count = await service.getOverrideCount(req.params.tenantId);
      res.json(count);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /flag/:flagId
   * Get all overrides for a flag
   */
  router.get('/flag/:flagId', async (req: Request, res: Response): Promise<void> => {
    try {
      const overrides = await service.findByFlag(req.params.flagId);
      res.json(overrides);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /:id
   * Get override by ID
   */
  router.get('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const override = await service.findById(req.params.id);
      if (!override) {
        res.status(404).json({ error: 'Override not found' });
        return;
      }
      res.json(override);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * POST /
   * Create or update an override
   * Body: { flagId: string, tenantId: string, enabled: boolean, reason?: string, expiresAt?: Date }
   */
  router.post('/', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;

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

  /**
   * POST /by-code
   * Create override by flag code
   * Body: { flagCode: string, tenantId: string, enabled: boolean, reason?: string, expiresAt?: Date }
   */
  router.post('/by-code', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;
      const { flagCode, tenantId, enabled, reason, expiresAt } = req.body;

      if (!flagCode || !tenantId || enabled === undefined) {
        res.status(400).json({ error: 'flagCode, tenantId, and enabled are required' });
        return;
      }

      const override = await service.createByFlagCode(
        flagCode,
        tenantId,
        enabled,
        reason,
        expiresAt ? new Date(expiresAt) : undefined,
        userId
      );

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

  /**
   * POST /bulk
   * Apply multiple overrides for a tenant
   * Body: { tenantId: string, overrides: [{ flagCode: string, enabled: boolean, reason?: string, expiresAt?: Date }] }
   */
  router.post('/bulk', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;

      const result = await service.bulkUpsert(req.body, userId);
      res.status(201).json({
        success: true,
        created: result.length,
        overrides: result,
      });
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /copy
   * Copy overrides from one tenant to another
   * Body: { sourceTenantId: string, targetTenantId: string }
   */
  router.post('/copy', async (req: Request, res: Response): Promise<void> => {
    try {
      const userId = (req as any).user?.id;
      const { sourceTenantId, targetTenantId } = req.body;

      if (!sourceTenantId || !targetTenantId) {
        res.status(400).json({ error: 'sourceTenantId and targetTenantId are required' });
        return;
      }

      const result = await service.copyOverrides(sourceTenantId, targetTenantId, userId);
      res.status(201).json({
        success: true,
        copied: result.length,
        overrides: result,
      });
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PUT /:id
   * Update an override
   * Body: { enabled?: boolean, reason?: string, expiresAt?: Date | null }
   */
  router.put('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const override = await service.update(req.params.id, req.body);
      if (!override) {
        res.status(404).json({ error: 'Override not found' });
        return;
      }
      res.json(override);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PATCH /:id/extend
   * Extend override expiration
   * Body: { expiresAt: Date }
   */
  router.patch('/:id/extend', async (req: Request, res: Response): Promise<void> => {
    try {
      const { expiresAt } = req.body;

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

      const override = await service.extendExpiration(req.params.id, new Date(expiresAt));
      if (!override) {
        res.status(404).json({ error: 'Override not found' });
        return;
      }

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

  /**
   * PATCH /:id/make-permanent
   * Remove expiration from an override
   */
  router.patch('/:id/make-permanent', async (req: Request, res: Response): Promise<void> => {
    try {
      const override = await service.removeExpiration(req.params.id);
      if (!override) {
        res.status(404).json({ error: 'Override not found' });
        return;
      }

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

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

  /**
   * DELETE /:id
   * Delete an override
   */
  router.delete('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const deleted = await service.delete(req.params.id);
      if (!deleted) {
        res.status(404).json({ error: 'Override not found' });
        return;
      }

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

  /**
   * DELETE /tenant/:tenantId
   * Delete all overrides for a tenant
   */
  router.delete('/tenant/:tenantId', async (req: Request, res: Response): Promise<void> => {
    try {
      const deleted = await service.deleteAllForTenant(req.params.tenantId);
      res.json({
        success: true,
        deleted,
        message: `Deleted ${deleted} overrides for tenant ${req.params.tenantId}`,
      });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * DELETE /flag/:flagId
   * Delete all overrides for a flag
   */
  router.delete('/flag/:flagId', async (req: Request, res: Response): Promise<void> => {
    try {
      const deleted = await service.deleteAllForFlag(req.params.flagId);
      res.json({
        success: true,
        deleted,
        message: `Deleted ${deleted} overrides for flag ${req.params.flagId}`,
      });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * POST /cleanup-expired
   * Clean up expired overrides
   */
  router.post('/cleanup-expired', async (_req: Request, res: Response): Promise<void> => {
    try {
      const deleted = await service.cleanupExpired();
      res.json({
        success: true,
        deleted,
        message: `Deleted ${deleted} expired overrides`,
      });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
