import { Body, Controller, Get, Param, Post, Query, UseGuards } from "@nestjs/common";
import {
  ApiBearerAuth,
  ApiOperation,
  ApiQuery,
  ApiResponse,
  ApiTags,
} from "@nestjs/swagger";
import { ApiKeyGuard } from "../common/auth/api-key.guard";
import { MerchantAuth } from "../common/auth/auth-context.decorator";
import type { ApiKeyAuthContext } from "../common/auth/auth.types";
import { ApiErrorResponse } from "../common/swagger/api-error.schema";
import { CreateRefundDto } from "./dto/create-refund.dto";
import { RefundDto, RefundListDto } from "./dto/refund.dto";
import { RefundService } from "./refund.service";

@ApiTags("Refunds")
@ApiBearerAuth("bearerAuth")
@ApiResponse({ status: 401, description: "API key faltante, inválida o revocada.", type: ApiErrorResponse })
@ApiResponse({ status: 403, description: "Merchant inactivo.", type: ApiErrorResponse })
@ApiResponse({ status: 429, description: "Rate limit excedido.", type: ApiErrorResponse })
@Controller("refunds")
@UseGuards(ApiKeyGuard)
export class RefundController {
  constructor(private readonly service: RefundService) {}

  @Post()
  @ApiOperation({
    operationId: "refundsCreate",
    summary: "Crear refund",
    description:
      "Reembolsa total o parcialmente el último attempt aprobado del intent. Si se omite `amount`, reembolsa el remanente. " +
      "Llama al provider y, si la respuesta es `approved`, actualiza el intent a `partially_refunded` o `refunded`.",
  })
  @ApiResponse({ status: 201, type: RefundDto })
  @ApiResponse({
    status: 400,
    description: "Intent sin attempt aprobado, ya reembolsado totalmente, o monto > remanente.",
    type: ApiErrorResponse,
  })
  @ApiResponse({ status: 404, description: "Intent no encontrado.", type: ApiErrorResponse })
  create(@MerchantAuth() auth: ApiKeyAuthContext, @Body() dto: CreateRefundDto) {
    return this.service.create(auth.merchantId, dto);
  }

  @Get()
  @ApiOperation({ operationId: "refundsList", summary: "Listar refunds" })
  @ApiQuery({ name: "limit", required: false, type: Number, example: 20 })
  @ApiQuery({ name: "cursor", required: false, type: String })
  @ApiQuery({ name: "intentId", required: false, type: String, description: "Filtrar por intent específico." })
  @ApiResponse({ status: 200, type: RefundListDto })
  list(
    @MerchantAuth() auth: ApiKeyAuthContext,
    @Query("limit") limit?: string,
    @Query("cursor") cursor?: string,
    @Query("intentId") intentId?: string,
  ) {
    return this.service.list(auth.merchantId, {
      limit: limit ? Number(limit) : undefined,
      cursor,
      intentId,
    });
  }

  @Get(":id")
  @ApiOperation({ operationId: "refundsRetrieve", summary: "Obtener refund por ID" })
  @ApiResponse({ status: 200, type: RefundDto })
  @ApiResponse({ status: 404, description: "Refund no encontrado.", type: ApiErrorResponse })
  findOne(@MerchantAuth() auth: ApiKeyAuthContext, @Param("id") id: string) {
    return this.service.findOne(auth.merchantId, id);
  }
}
