import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Query,
  UseGuards,
} from "@nestjs/common";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { PaymentIntentSnapshot } from "@edr/types";
import { ServiceAuthGuard } from "../../common/guards/service-auth.guard";
import {
  InitiatePaymentRequestDto,
  IntentReferenceQueryDto,
} from "./dto/initiate-payment.dto";
import { ConfirmPaymentDto } from "./dto/confirm-payment.dto";
import { IntentsService } from "./intents.service";

/**
 * Internal surface — called only by the domain apps (service-authenticated), never by
 * browsers. Domain validation ("is this booking payable", authoritative amount) has already
 * happened in the calling app.
 */
@ApiTags("Payments (internal)")
@UseGuards(ServiceAuthGuard)
@Controller("payments")
export class IntentsController {
  constructor(private readonly intentsService: IntentsService) {}

  @Post("initiate")
  @ApiOperation({
    summary:
      "Create (or idempotently reuse) a payment intent and open a provider session",
    description:
      "One active intent per (service, referenceType, referenceId). Re-initiating a non-terminal intent returns the existing clientAction.",
  })
  async initiate(
    @Body() dto: InitiatePaymentRequestDto,
  ): Promise<PaymentIntentSnapshot> {
    return this.intentsService.initiate(dto);
  }

  @Get("intents/:id")
  @ApiOperation({
    summary: "Intent status by id (pull/reconcile)",
    description:
      "Stale non-terminal intents trigger a provider status query before returning.",
  })
  async getIntent(
    @Param("id", ParseUUIDPipe) id: string,
  ): Promise<PaymentIntentSnapshot> {
    return this.intentsService.getIntent(id);
  }

  @Get("intents")
  @ApiOperation({
    summary: "Active intent status by domain reference (pull/reconcile)",
  })
  async getIntentByReference(
    @Query() query: IntentReferenceQueryDto,
  ): Promise<PaymentIntentSnapshot> {
    return this.intentsService.getIntentByReference(
      query.service,
      query.referenceType,
      query.referenceId,
    );
  }

  @Post("intents/:id/confirm")
  @ApiOperation({
    summary: "Confirm an OTP-based payment intent (e.g. CAC Bank)",
    description:
      "Submits the SMS OTP to complete payment. Only supported for providers that use COLLECT_OTP clientAction.",
  })
  async confirm(
    @Param("id", ParseUUIDPipe) id: string,
    @Body() dto: ConfirmPaymentDto,
  ): Promise<PaymentIntentSnapshot> {
    return this.intentsService.confirm(id, dto);
  }
}
