/**
 * Marketplace Controller for SentryAgent.ai AgentIdP.
 * HTTP handlers for unauthenticated public marketplace endpoints.
 * No business logic — delegates to MarketplaceService.
 */

import { Request, Response, NextFunction } from 'express';
import { MarketplaceService } from '../services/MarketplaceService.js';
import { marketplaceQuerySchema } from '../utils/validators.js';
import { ValidationError } from '../utils/errors.js';
import { IMarketplaceFilters } from '../types/index.js';

/**
 * Controller for the public Agent Marketplace endpoints.
 * Receives MarketplaceService via constructor injection.
 */
export class MarketplaceController {
  /**
   * @param marketplaceService - The marketplace service.
   */
  constructor(private readonly marketplaceService: MarketplaceService) {}

  /**
   * Handles GET /marketplace/agents — returns a paginated list of public agents.
   * Unauthenticated. Supports ?q=, ?capability=, ?publisher= query filters.
   *
   * @param req - Express request with optional query filters.
   * @param res - Express response.
   * @param next - Express next function.
   */
  listPublicAgents = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
      const { error, value } = marketplaceQuerySchema.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: IMarketplaceFilters = {
        page: value.page as number,
        limit: value.limit as number,
        q: value.q as string | undefined,
        capability: value.capability as string | undefined,
        publisher: value.publisher as string | undefined,
      };
      /* eslint-enable @typescript-eslint/no-unsafe-member-access */

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

  /**
   * Handles GET /marketplace/agents/:agentId — returns a single public agent with DID document.
   * Unauthenticated. Returns 404 if the agent is private or inactive.
   *
   * @param req - Express request with agentId path param.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getPublicAgent = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const { agentId } = req.params;
      const agent = await this.marketplaceService.getPublicAgent(agentId);
      res.status(200).json(agent);
    } catch (err) {
      next(err);
    }
  };
}
