import {
  BadRequestException,
  Controller,
  Headers,
  HttpCode,
  Param,
  Post,
  RawBodyRequest,
  Req,
} from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { Provider } from "@prisma/client";
import { Request } from "express";
import { ApiErrorResponse } from "../common/swagger/api-error.schema";
import { WebhookInboundService } from "./webhook-inbound.service";

@ApiTags("Webhooks · Inbound")
@Controller("webhooks/in")
export class WebhookInboundController {
  constructor(private readonly service: WebhookInboundService) {}

  @Post(":provider/:providerConfigId")
  @HttpCode(200)
  @ApiOperation({
    operationId: "webhooksInboundReceive",
    summary: "Recibir webhook de provider",
    description:
      "Endpoint público sin auth de API key — el provider se autentica con su propia firma HMAC, verificada por el adapter. " +
      "El body se procesa como **raw** para preservar la firma. " +
      "Persistimos toda recepción (incluso inválidas) en `WebhookEventIn` para trazabilidad. " +
      "Si la firma valida y el `providerPaymentId` matchea un attempt, se actualiza intent/attempt y se emite webhook al merchant.",
  })
  @ApiResponse({
    status: 200,
    description: "Procesado (o deduplicado).",
    schema: {
      type: "object",
      properties: {
        received: { type: "boolean", example: true },
        eventId: { type: "string", example: "wei_01HXYZABCDEFGHJKMNPQRSTV" },
        deduped: { type: "boolean", example: false },
      },
    },
  })
  @ApiResponse({ status: 400, description: "Provider config no encontrada o provider mismatched.", type: ApiErrorResponse })
  @ApiResponse({ status: 401, description: "Firma HMAC inválida.", type: ApiErrorResponse })
  async receive(
    @Param("provider") provider: string,
    @Param("providerConfigId") providerConfigId: string,
    @Req() req: RawBodyRequest<Request>,
    @Headers() headers: Record<string, string>,
  ) {
    if (!Object.values(Provider).includes(provider as Provider)) {
      throw new BadRequestException(`Unknown provider: ${provider}`);
    }
    const rawBody = req.rawBody?.toString("utf8");
    if (!rawBody) throw new BadRequestException("Missing request body");

    const normalizedHeaders = Object.fromEntries(
      Object.entries(headers).map(([k, v]) => [k.toLowerCase(), Array.isArray(v) ? v[0] : v]),
    );

    return this.service.receive(
      provider as Provider,
      providerConfigId,
      rawBody,
      normalizedHeaders,
    );
  }
}
