import {
  Body,
  Controller,
  Get,
  Param,
  Patch,
  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 { RequireFullScopeGuard } from "../common/auth/restricted-scope.guard";
import { ApiErrorResponse } from "../common/swagger/api-error.schema";
import { CreateProviderConfigDto } from "./dto/create-provider-config.dto";
import { ProviderConfigDto, ProviderConfigListDto } from "./dto/provider-config.dto";
import { UpdateProviderConfigDto } from "./dto/update-provider-config.dto";
import { ProviderConfigService } from "./provider-config.service";

@ApiTags("Provider Configs")
@ApiBearerAuth("bearerAuth")
@ApiResponse({ status: 401, description: "API key faltante, inválida o revocada.", type: ApiErrorResponse })
@ApiResponse({ status: 403, description: "La API key no tiene scope `full` o el merchant está inactivo.", type: ApiErrorResponse })
@ApiResponse({ status: 429, description: "Rate limit excedido.", type: ApiErrorResponse })
@Controller("provider-configs")
@UseGuards(ApiKeyGuard, RequireFullScopeGuard)
export class ProviderConfigController {
  constructor(private readonly service: ProviderConfigService) {}

  @Post()
  @ApiOperation({
    operationId: "providerConfigsCreate",
    summary: "Crear configuración de provider",
    description:
      "Registra credenciales de un provider (dLocal, Bancard, etc.) para una combinación `(provider, country, mode)`. " +
      "Las credenciales se encriptan en reposo con AES-256-GCM y **nunca** se devuelven por API.",
  })
  @ApiResponse({ status: 201, type: ProviderConfigDto })
  @ApiResponse({ status: 400, description: "Validación de body falló.", type: ApiErrorResponse })
  @ApiResponse({ status: 409, description: "Ya existe una config para esa combinación.", type: ApiErrorResponse })
  create(@MerchantAuth() auth: ApiKeyAuthContext, @Body() dto: CreateProviderConfigDto) {
    return this.service.create(auth.merchantId, dto);
  }

  @Get()
  @ApiOperation({ operationId: "providerConfigsList", summary: "Listar configuraciones de provider" })
  @ApiQuery({ name: "limit", required: false, type: Number, example: 20 })
  @ApiQuery({ name: "cursor", required: false, type: String })
  @ApiResponse({ status: 200, type: ProviderConfigListDto })
  list(
    @MerchantAuth() auth: ApiKeyAuthContext,
    @Query("limit") limit?: string,
    @Query("cursor") cursor?: string,
  ) {
    return this.service.list(auth.merchantId, limit ? Number(limit) : undefined, cursor);
  }

  @Get(":id")
  @ApiOperation({ operationId: "providerConfigsRetrieve", summary: "Obtener provider config por ID" })
  @ApiResponse({ status: 200, type: ProviderConfigDto })
  @ApiResponse({ status: 404, description: "No encontrada.", type: ApiErrorResponse })
  findOne(@MerchantAuth() auth: ApiKeyAuthContext, @Param("id") id: string) {
    return this.service.findOne(auth.merchantId, id);
  }

  @Patch(":id")
  @ApiOperation({
    operationId: "providerConfigsUpdate",
    summary: "Actualizar provider config",
    description: "Si se envían `credentials`, **reemplazan** las anteriores (se re-encriptan).",
  })
  @ApiResponse({ status: 200, type: ProviderConfigDto })
  @ApiResponse({ status: 400, description: "Validación de body falló.", type: ApiErrorResponse })
  @ApiResponse({ status: 404, description: "No encontrada.", type: ApiErrorResponse })
  update(
    @MerchantAuth() auth: ApiKeyAuthContext,
    @Param("id") id: string,
    @Body() dto: UpdateProviderConfigDto,
  ) {
    return this.service.update(auth.merchantId, id, dto);
  }
}
