import {
  Body,
  Controller,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
} from "@nestjs/common";
import {
  ApiBearerAuth,
  ApiOperation,
  ApiQuery,
  ApiResponse,
  ApiTags,
} from "@nestjs/swagger";
import { InvoiceStatus } from "@prisma/client";
import { AdminUserGuard } from "../admin-auth/admin-user.guard";
import { ApiErrorResponse } from "../common/swagger/api-error.schema";
import { GenerateInvoiceDto } from "./dto/generate-invoice.dto";
import { InvoiceDto, InvoiceListDto } from "./dto/invoice.dto";
import { InvoiceService } from "./invoice.service";

@ApiTags("Admin · Billing")
@ApiBearerAuth("adminUserAuth")
@ApiResponse({ status: 401, description: "Token admin faltante o inválido.", type: ApiErrorResponse })
@Controller("admin/invoices")
@UseGuards(AdminUserGuard)
export class InvoiceAdminController {
  constructor(private readonly service: InvoiceService) {}

  @Get()
  @ApiOperation({
    operationId: "adminInvoicesList",
    summary: "Listar facturas",
  })
  @ApiQuery({ name: "limit", required: false, type: Number, example: 20 })
  @ApiQuery({ name: "cursor", required: false, type: String })
  @ApiQuery({ name: "status", required: false, enum: InvoiceStatus })
  @ApiQuery({ name: "period", required: false, example: "2026-06" })
  @ApiQuery({ name: "merchantId", required: false, type: String })
  @ApiResponse({ status: 200, type: InvoiceListDto })
  list(
    @Query("limit") limit?: string,
    @Query("cursor") cursor?: string,
    @Query("status") status?: InvoiceStatus,
    @Query("period") period?: string,
    @Query("merchantId") merchantId?: string,
  ) {
    return this.service.list({
      limit: limit ? Number(limit) : undefined,
      cursor,
      status,
      period,
      merchantId,
    });
  }

  @Get(":id")
  @ApiOperation({ operationId: "adminInvoicesRetrieve", summary: "Detalle de factura" })
  @ApiResponse({ status: 200, type: InvoiceDto })
  @ApiResponse({ status: 404, description: "Factura no encontrada.", type: ApiErrorResponse })
  findOne(@Param("id") id: string) {
    return this.service.findOne(id);
  }

  @Post("generate")
  @ApiOperation({
    operationId: "adminInvoicesGenerate",
    summary: "Generar facturas para un período",
    description:
      "Genera la factura del período indicado para los comercios solicitados (o todos los activos si no se pasa merchantId). " +
      "Idempotente: si ya existe `(merchantId, period)` se skipea.",
  })
  @ApiResponse({
    status: 201,
    description: "Resultado de la generación masiva.",
    schema: {
      type: "object",
      properties: {
        generated: { type: "array", items: { type: "object" } },
        skipped: {
          type: "array",
          items: {
            type: "object",
            properties: {
              merchantId: { type: "string" },
              reason: { type: "string" },
            },
          },
        },
      },
    },
  })
  generate(@Body() dto: GenerateInvoiceDto) {
    return this.service.generate({
      merchantId: dto.merchantId,
      period: dto.period,
    });
  }

  @Patch(":id/mark-paid")
  @ApiOperation({
    operationId: "adminInvoicesMarkPaid",
    summary: "Marcar factura como pagada manualmente",
  })
  @ApiResponse({ status: 200, type: InvoiceDto })
  @ApiResponse({ status: 404, description: "Factura no encontrada.", type: ApiErrorResponse })
  @ApiResponse({ status: 409, description: "Factura ya estaba paid/void.", type: ApiErrorResponse })
  markPaid(@Param("id") id: string) {
    return this.service.markPaid(id);
  }
}
