/**
 * Analytics Controller for SentryAgent.ai AgentIdP.
 * HTTP handlers for tenant analytics endpoints.
 * No business logic — delegates all data access to AnalyticsService.
 * All handlers enforce tenant scoping via req.user.organization_id.
 */

import { Request, Response, NextFunction } from 'express';
import { AnalyticsService } from '../services/AnalyticsService.js';
import { AuthenticationError, ValidationError } from '../utils/errors.js';

/** Maximum permitted value for the `days` query parameter. */
const MAX_DAYS = 90;
/** Default number of days returned when `days` is not specified. */
const DEFAULT_DAYS = 30;

/**
 * Controller for the analytics endpoints.
 * Receives AnalyticsService via constructor injection.
 */
export class AnalyticsController {
  /**
   * @param analyticsService - The analytics data service.
   */
  constructor(private readonly analyticsService: AnalyticsService) {}

  /**
   * Handles GET /analytics/tokens — returns daily token issuance trend.
   * Query parameter `days` (optional, default 30, max 90).
   * Responds 400 if `days` exceeds the maximum.
   * Responds 401 if the request is not authenticated.
   *
   * @param req - Express request. Must have req.user populated.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getTokenTrend = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      const daysParam = req.query['days'];
      const days = daysParam !== undefined ? parseInt(String(daysParam), 10) : DEFAULT_DAYS;

      if (isNaN(days) || days < 1) {
        throw new ValidationError('Query parameter `days` must be a positive integer.', {
          field: 'days',
        });
      }

      if (days > MAX_DAYS) {
        throw new ValidationError(
          `Query parameter \`days\` must not exceed ${MAX_DAYS}.`,
          { field: 'days', max: MAX_DAYS, provided: days },
        );
      }

      const tenantId = req.user.organization_id ?? 'org_system';
      const trend = await this.analyticsService.getTokenTrend(tenantId, days);

      res.status(200).json(trend);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles GET /analytics/agents/activity — returns agent activity heatmap data.
   * Responds 401 if the request is not authenticated.
   *
   * @param req - Express request. Must have req.user populated.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getAgentActivity = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      const tenantId = req.user.organization_id ?? 'org_system';
      const activity = await this.analyticsService.getAgentActivity(tenantId);

      res.status(200).json(activity);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles GET /analytics/agents — returns per-agent usage summary for the current month.
   * Responds 401 if the request is not authenticated.
   *
   * @param req - Express request. Must have req.user populated.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getAgentSummary = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      const tenantId = req.user.organization_id ?? 'org_system';
      const summary = await this.analyticsService.getAgentUsageSummary(tenantId);

      res.status(200).json(summary);
    } catch (err) {
      next(err);
    }
  };
}
