import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Query,
  Res,
} from "@nestjs/common";
import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger";
import type { Response } from "express";
import { CurrentUser } from "@edr/api-common";

import {
  type AuthUserPayload,
  resolveAuthUserId,
} from "../../common/resolve-auth-user-id";
import { sendPdf } from "./billing.controller";
import { BillingService } from "./billing.service";
import { PayInvoiceDto } from "./dto/pay-invoice.dto";

/**
 * Customer-facing billing endpoints. Unlike {@link BillingController} (admin,
 * org-wide), every route here is force-scoped to the signed-in customer's
 * company — they only ever see and pay their own invoices.
 */
@ApiTags("billing")
@ApiBearerAuth()
@Controller("billing")
export class PortalBillingController {
  constructor(private readonly billingService: BillingService) {}

  @Get("my-invoices")
  @ApiOperation({ summary: "List the signed-in customer's invoices" })
  findMine(
    @CurrentUser() user: AuthUserPayload,
    @Query("source") source?: string,
    @Query("sourceId") sourceId?: string,
  ) {
    return this.billingService.findForUser(resolveAuthUserId(user), {
      source,
      sourceId,
    });
  }

  @Get("my-invoices/:id")
  @ApiOperation({ summary: "Get one of the customer's invoices (+ line items)" })
  findMineById(
    @Param("id", ParseUUIDPipe) id: string,
    @CurrentUser() user: AuthUserPayload,
  ) {
    return this.billingService.findByIdForUser(id, resolveAuthUserId(user));
  }

  @Get("my-invoices/:id/document")
  @ApiOperation({ summary: "Download one of the customer's invoice PDFs" })
  async document(
    @Param("id", ParseUUIDPipe) id: string,
    @CurrentUser() user: AuthUserPayload,
    @Res() res: Response,
  ) {
    const { filename, buffer } = await this.billingService.documentForUser(
      id,
      resolveAuthUserId(user),
    );
    sendPdf(res, filename, buffer);
  }

  @Get("my-invoices/:id/receipt")
  @ApiOperation({ summary: "Download one of the customer's payment receipt PDFs" })
  async receipt(
    @Param("id", ParseUUIDPipe) id: string,
    @CurrentUser() user: AuthUserPayload,
    @Res() res: Response,
  ) {
    const { filename, buffer } = await this.billingService.receiptForUser(
      id,
      resolveAuthUserId(user),
    );
    sendPdf(res, filename, buffer);
  }

  @Post("my-invoices/:id/pay")
  @ApiOperation({ summary: "Initiate payment for one of the customer's invoices" })
  pay(
    @Param("id", ParseUUIDPipe) id: string,
    @CurrentUser() user: AuthUserPayload,
    @Body() dto: PayInvoiceDto,
  ) {
    return this.billingService.payInvoiceForUser(id, resolveAuthUserId(user), {
      method: dto.method,
      platform: dto.platform ?? "web",
      payerAccount: dto.payerAccount,
      returnUrl: dto.returnUrl,
      failureUrl: dto.failureUrl,
    });
  }
}
