/**
 * Tier Controller for SentryAgent.ai AgentIdP.
 * HTTP handlers for tier status and upgrade endpoints.
 * No business logic — delegates entirely to TierService.
 */

import { Request, Response, NextFunction } from 'express';
import { TierService } from '../services/TierService.js';
import { AuthenticationError, ValidationError } from '../utils/errors.js';
import { isTierName } from '../config/tiers.js';

/**
 * Controller for tenant tier management endpoints.
 * Receives TierService via constructor injection.
 */
export class TierController {
  /**
   * @param tierService - The tier management service.
   */
  constructor(private readonly tierService: TierService) {}

  /**
   * Handles GET /api/tiers/status — returns the current tier, limits, and usage.
   *
   * Response: 200 ITierStatus
   * Errors: 401 when unauthenticated.
   *
   * @param req - Express request. Must have req.user populated.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getStatus = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      const orgId = req.user.organization_id;
      if (!orgId) {
        throw new AuthenticationError('organization_id is required in token.');
      }

      const status = await this.tierService.getStatus(orgId);
      res.status(200).json(status);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles POST /api/tiers/upgrade — initiates a Stripe checkout session for a tier upgrade.
   *
   * Request body: { target_tier: 'pro' | 'enterprise' }
   * Response: 200 { checkoutUrl: string }
   * Errors: 400 when target_tier is missing/invalid or is not an upgrade.
   *         401 when unauthenticated.
   *
   * @param req - Express request. Must have req.user populated.
   * @param res - Express response.
   * @param next - Express next function.
   */
  initiateUpgrade = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      const orgId = req.user.organization_id;
      if (!orgId) {
        throw new AuthenticationError('organization_id is required in token.');
      }

      const body = req.body as { target_tier?: unknown };
      const rawTargetTier = body.target_tier;

      if (!rawTargetTier || typeof rawTargetTier !== 'string') {
        throw new ValidationError('target_tier is required.', { received: rawTargetTier });
      }

      if (!isTierName(rawTargetTier)) {
        throw new ValidationError(
          `target_tier must be one of: free, pro, enterprise.`,
          { received: rawTargetTier },
        );
      }

      const result = await this.tierService.initiateUpgrade(orgId, rawTargetTier);
      res.status(200).json(result);
    } catch (err) {
      next(err);
    }
  };
}
