/**
 * Usage Controller
 *
 * REST API endpoints for usage tracking
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { UsageTrackingService } from '../services';
import { RecordUsageDto, UpdateUsageDto, IncrementUsageDto, UsageMetrics } from '../dto';

export class UsageController {
  public router: Router;
  private service: UsageTrackingService;

  constructor(dataSource: DataSource) {
    this.router = Router();
    this.service = new UsageTrackingService(dataSource);
    this.initializeRoutes();
  }

  private initializeRoutes(): void {
    // Current usage
    this.router.get('/tenant/:tenantId/current', this.getCurrentUsage.bind(this));
    this.router.get('/tenant/:tenantId/summary', this.getUsageSummary.bind(this));
    this.router.get('/tenant/:tenantId/limits', this.checkLimits.bind(this));

    // Usage history
    this.router.get('/tenant/:tenantId/history', this.getUsageHistory.bind(this));
    this.router.get('/tenant/:tenantId/report', this.getUsageReport.bind(this));

    // Record usage
    this.router.post('/', this.recordUsage.bind(this));
    this.router.put('/:id', this.updateUsage.bind(this));
    this.router.post('/increment', this.incrementMetric.bind(this));
  }

  /**
   * GET /usage/tenant/:tenantId/current
   * Get current usage for tenant
   */
  private async getCurrentUsage(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const usage = await this.service.getCurrentUsage(req.params.tenantId);
      res.json({ data: usage });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /usage/tenant/:tenantId/summary
   * Get usage summary with limits
   */
  private async getUsageSummary(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const summary = await this.service.getUsageSummary(req.params.tenantId);
      res.json({ data: summary });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /usage/tenant/:tenantId/limits
   * Check if tenant exceeds limits
   */
  private async checkLimits(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const limits = await this.service.checkLimits(req.params.tenantId);
      res.json({ data: limits });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /usage/tenant/:tenantId/history
   * Get usage history
   */
  private async getUsageHistory(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate } = req.query;

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

      const history = await this.service.getUsageHistory(
        req.params.tenantId,
        new Date(startDate as string),
        new Date(endDate as string)
      );

      res.json({ data: history });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /usage/tenant/:tenantId/report
   * Get usage report
   */
  private async getUsageReport(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate, granularity } = req.query;

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

      const report = await this.service.getUsageReport(
        req.params.tenantId,
        new Date(startDate as string),
        new Date(endDate as string),
        (granularity as 'daily' | 'weekly' | 'monthly') || 'monthly'
      );

      res.json({ data: report });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /usage
   * Record usage for period
   */
  private async recordUsage(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const dto: RecordUsageDto = req.body;
      const usage = await this.service.recordUsage(dto);
      res.status(201).json({ data: usage });
    } catch (error) {
      next(error);
    }
  }

  /**
   * PUT /usage/:id
   * Update usage record
   */
  private async updateUsage(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const dto: UpdateUsageDto = req.body;
      const usage = await this.service.update(req.params.id, dto);
      res.json({ data: usage });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /usage/increment
   * Increment a specific metric
   */
  private async incrementMetric(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const dto: IncrementUsageDto = req.body;
      await this.service.incrementMetric(
        dto.tenantId,
        dto.metric as keyof UsageMetrics,
        dto.amount || 1
      );
      res.json({ success: true });
    } catch (error) {
      next(error);
    }
  }
}
