import { BadRequestException, Body, Controller, Get, Param, Post, Req, UseGuards } from '@nestjs/common'
import { ActorService } from '../auth/actor.service.js'
import { clientIp } from '../auth/client-ip.js'
import { CurrentUser } from '../auth/current-user.decorator.js'
import { JwtAuthGuard } from '../auth/jwt-auth.guard.js'
import type { AuthentikJwtPayload } from '../auth/jwt-payload.interface.js'
import { BillingService } from './billing.service.js'

// Customer-admin billing reads, scoped to a single tenant the caller belongs
// to. Lives in BillingModule (not TenantsModule) to avoid a module cycle:
// TenantsModule → BillingModule → UsersModule → TenantsModule. Only
// JwtAuthGuard here (any portal user); per-tenant membership is enforced in
// BillingService.tenantInvoicesForActor.
@Controller('tenants')
@UseGuards(JwtAuthGuard)
export class CustomerBillingController {
  constructor(
    private readonly billing: BillingService,
    private readonly actor: ActorService,
  ) {}

  @Get(':slug/invoices')
  async invoices(@Param('slug') slug: string, @CurrentUser() jwt: AuthentikJwtPayload) {
    const user = await this.actor.resolve(jwt)
    return this.billing.tenantInvoicesForActor(slug, user)
  }

  // The card currently on file (or null). Read-only.
  @Get(':slug/payment-method')
  async paymentMethod(@Param('slug') slug: string, @CurrentUser() jwt: AuthentikJwtPayload) {
    const user = await this.actor.resolve(jwt)
    return this.billing.getPaymentMethod(slug, user)
  }

  // Start a card update — returns the SetupIntent client secret + publishable
  // key for the portal to confirm with Stripe Elements.
  @Post(':slug/payment-method/setup-intent')
  async setupIntent(@Param('slug') slug: string, @CurrentUser() jwt: AuthentikJwtPayload) {
    const user = await this.actor.resolve(jwt)
    return this.billing.createPaymentSetupIntent(slug, user)
  }

  // Finish the update: set the confirmed payment method as the default.
  @Post(':slug/payment-method/default')
  async setDefault(
    @Param('slug') slug: string,
    @Body('paymentMethodId') paymentMethodId: string,
    @CurrentUser() jwt: AuthentikJwtPayload,
    @Req() req: Parameters<typeof clientIp>[0],
  ) {
    if (!paymentMethodId) throw new BadRequestException('paymentMethodId is required')
    const user = await this.actor.resolve(jwt)
    return this.billing.setDefaultPaymentMethod(slug, user, paymentMethodId, {
      userId: String(user._id),
      email: user.email,
      ip: clientIp(req),
    })
  }
}
