/**
 * Audit Controller for SentryAgent.ai AgentIdP.
 * HTTP handlers for GET /audit and GET /audit/:eventId.
 */

import { Request, Response, NextFunction } from 'express';
import { AuditService } from '../services/AuditService.js';
import { auditQuerySchema } from '../utils/validators.js';
import {
  ValidationError,
  AuthenticationError,
} from '../utils/errors.js';
import { IAuditListFilters } from '../types/index.js';

/**
 * Controller for the Audit Log endpoints.
 * Authorization is enforced by OPA middleware — no per-handler scope checks required.
 */
export class AuditController {
  /**
   * @param auditService - The audit log service.
   */
  constructor(private readonly auditService: AuditService) {}

  /**
   * Handles GET /audit — queries the audit log with optional filters.
   * Requires Bearer token with `audit:read` scope.
   *
   * @param req - Express request with optional query filters.
   * @param res - Express response.
   * @param next - Express next function.
   */
  queryAuditLog = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
      const { error, value } = auditQuerySchema.validate(req.query, { abortEarly: false });
      if (error) {
        throw new ValidationError('Invalid query parameter value.', {
          details: error.details.map((d) => ({ field: d.path.join('.'), reason: d.message })),
        });
      }

      /* eslint-disable @typescript-eslint/no-unsafe-member-access */
      const filters: IAuditListFilters = {
        page: value.page as number,
        limit: value.limit as number,
        agentId: value.agentId as string | undefined,
        action: value.action as IAuditListFilters['action'],
        outcome: value.outcome as IAuditListFilters['outcome'],
        fromDate: value.fromDate as string | undefined,
        toDate: value.toDate as string | undefined,
      };
      /* eslint-enable @typescript-eslint/no-unsafe-member-access */

      const result = await this.auditService.queryEvents(filters);
      res.status(200).json(result);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles GET /audit/:eventId — retrieves a single audit event.
   * Requires Bearer token with `audit:read` scope.
   *
   * @param req - Express request with eventId path param.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getAuditEventById = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      if (!req.user) {
        throw new AuthenticationError();
      }

      const { eventId } = req.params;
      const event = await this.auditService.getEventById(eventId);
      res.status(200).json(event);
    } catch (err) {
      next(err);
    }
  };
}
