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 { ApiErrorResponse } from "../common/swagger/api-error.schema";
import { CustomerService } from "./customer.service";
import { CreateCustomerDto } from "./dto/create-customer.dto";
import { CustomerDto, CustomerListDto } from "./dto/customer.dto";
import { UpdateCustomerDto } from "./dto/update-customer.dto";

@ApiTags("Customers")
@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("customers")
@UseGuards(ApiKeyGuard)
export class CustomerController {
  constructor(private readonly service: CustomerService) {}

  @Post()
  @ApiOperation({
    operationId: "customersCreate",
    summary: "Crear customer",
    description:
      "Crea un customer asociado al merchant autenticado. Email y `(docType, docNumber)` son únicos por merchant.",
  })
  @ApiResponse({ status: 201, type: CustomerDto })
  @ApiResponse({ status: 400, description: "Validación de body falló.", type: ApiErrorResponse })
  @ApiResponse({ status: 409, description: "Email o documento ya existen para este merchant.", type: ApiErrorResponse })
  create(@MerchantAuth() auth: ApiKeyAuthContext, @Body() dto: CreateCustomerDto) {
    return this.service.create(auth.merchantId, dto);
  }

  @Get()
  @ApiOperation({ operationId: "customersList", summary: "Listar customers del merchant" })
  @ApiQuery({ name: "limit", required: false, type: Number, example: 20, description: "1–100. Default 20." })
  @ApiQuery({ name: "cursor", required: false, type: String })
  @ApiQuery({ name: "email", required: false, type: String, description: "Filtra por email exacto (case-insensitive)." })
  @ApiQuery({ name: "docNumber", required: false, type: String, description: "Filtra por número de documento exacto." })
  @ApiResponse({ status: 200, type: CustomerListDto })
  list(
    @MerchantAuth() auth: ApiKeyAuthContext,
    @Query("limit") limit?: string,
    @Query("cursor") cursor?: string,
    @Query("email") email?: string,
    @Query("docNumber") docNumber?: string,
  ) {
    return this.service.list(
      auth.merchantId,
      limit ? Number(limit) : undefined,
      cursor,
      { email, docNumber },
    );
  }

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

  @Patch(":id")
  @ApiOperation({ operationId: "customersUpdate", summary: "Actualizar customer" })
  @ApiResponse({ status: 200, type: CustomerDto })
  @ApiResponse({ status: 400, description: "Validación de body falló.", type: ApiErrorResponse })
  @ApiResponse({ status: 404, description: "Customer no encontrado.", type: ApiErrorResponse })
  @ApiResponse({ status: 409, description: "Email o documento en conflicto.", type: ApiErrorResponse })
  update(
    @MerchantAuth() auth: ApiKeyAuthContext,
    @Param("id") id: string,
    @Body() dto: UpdateCustomerDto,
  ) {
    return this.service.update(auth.merchantId, id, dto);
  }
}
