/**
 * DID Controller for SentryAgent.ai AgentIdP.
 * HTTP handlers for W3C DID document and AGNTCY agent card endpoints.
 * No business logic — delegates entirely to DIDService.
 */

import { Request, Response, NextFunction } from 'express';
import { DIDService } from '../services/DIDService.js';
import { AgentRepository } from '../repositories/AgentRepository.js';

const DECOMMISSIONED_CODE = 'AGENT_DECOMMISSIONED';
const DECOMMISSIONED_MESSAGE =
  'Agent has been decommissioned — DID Document is no longer active';
const DID_RESOLUTION_CONTENT_TYPE =
  'application/ld+json;profile="https://w3id.org/did-resolution"';

/**
 * Controller for W3C DID and AGNTCY agent card endpoints.
 * Receives DIDService and AgentRepository via constructor injection.
 */
export class DIDController {
  /**
   * @param didService - The DID management service.
   * @param _agentRepository - The agent repository (retained for future use, e.g. org-scoped pre-validation).
   */
  constructor(
    private readonly didService: DIDService,
    _agentRepository: AgentRepository,
  ) {}

  /**
   * Handles GET /.well-known/did.json — returns the instance-level DID Document.
   * Unauthenticated. Returns a W3C DID Document for the AgentIdP instance.
   *
   * @param _req - Express request (unused).
   * @param res - Express response.
   * @param next - Express next function.
   */
  getInstanceDIDDocument = async (
    _req: Request,
    res: Response,
    next: NextFunction,
  ): Promise<void> => {
    try {
      const doc = await this.didService.buildInstanceDIDDocument();
      res.json(doc);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles GET /agents/:agentId/did — returns the per-agent DID Document.
   * Unauthenticated. Returns 410 Gone if the agent is decommissioned.
   *
   * @param req - Express request with `agentId` path param.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getAgentDIDDocument = async (
    req: Request,
    res: Response,
    next: NextFunction,
  ): Promise<void> => {
    try {
      const { agentId } = req.params;
      const { document, deactivated } = await this.didService.buildAgentDIDDocument(agentId);

      if (deactivated) {
        res.status(410).json({
          code: DECOMMISSIONED_CODE,
          message: DECOMMISSIONED_MESSAGE,
        });
        return;
      }

      res.json(document);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles GET /agents/:agentId/did/resolve — returns the W3C DID Resolution result.
   * Requires authentication and OPA authorization. Sets the correct LD+JSON content type.
   *
   * @param req - Express request with `agentId` path param.
   * @param res - Express response.
   * @param next - Express next function.
   */
  resolveAgentDID = async (
    req: Request,
    res: Response,
    next: NextFunction,
  ): Promise<void> => {
    try {
      const { agentId } = req.params;
      const result = await this.didService.buildResolutionResult(agentId);
      res.set('Content-Type', DID_RESOLUTION_CONTENT_TYPE).json(result);
    } catch (err) {
      next(err);
    }
  };

  /**
   * Handles GET /agents/:agentId/did/card — returns the AGNTCY agent card.
   * Unauthenticated. Provides a machine-readable identity summary for AGNTCY consumers.
   *
   * @param req - Express request with `agentId` path param.
   * @param res - Express response.
   * @param next - Express next function.
   */
  getAgentCard = async (
    req: Request,
    res: Response,
    next: NextFunction,
  ): Promise<void> => {
    try {
      const { agentId } = req.params;
      const card = await this.didService.buildAgentCard(agentId);
      res.json(card);
    } catch (err) {
      next(err);
    }
  };
}
