import {
  Controller, Get, Post, Param, Query, Headers, NotFoundException,
} from '@nestjs/common';
import { InvoiceRepository } from '../../../infrastructure/repositories/invoice.repository';
import { UsageAggregateRepository } from '../../../infrastructure/repositories/usage-aggregate.repository';
import { CreatePaymentSessionUseCase } from '../../../application/use-cases/create-payment-session.use-case';
import { PaymentProviderRegistry } from '../../../infrastructure/payment-providers/payment-provider.registry';
import { PaymentProviderType } from '../../../domain/ports/payment-provider.port';

@Controller('api/v1/billing')
export class InvoiceController {
  constructor(
    private readonly invoiceRepo: InvoiceRepository,
    private readonly usageAggRepo: UsageAggregateRepository,
    private readonly createPaymentSession: CreatePaymentSessionUseCase,
    private readonly providerRegistry: PaymentProviderRegistry,
  ) {}

  @Get('invoices')
  async listInvoices(
    @Headers('x-tenant-id') tenantId: string,
    @Query('limit') limit = 20,
    @Query('offset') offset = 0,
  ) {
    const [invoices, total] = await this.invoiceRepo.findByTenantId(tenantId, +limit, +offset);
    return {
      data: invoices.map((inv) => ({
        id: inv.id,
        invoiceNumber: inv.invoiceNumber,
        status: inv.status,
        currency: inv.currency,
        totalAmount: inv.totalCents / 100,
        amountDue: inv.amountDueCents / 100,
        periodStart: inv.periodStart,
        periodEnd: inv.periodEnd,
        dueDate: inv.dueDate,
        paidAt: inv.paidAt,
        createdAt: inv.createdAt,
      })),
      total,
    };
  }

  @Get('invoices/:id')
  async getInvoice(
    @Headers('x-tenant-id') tenantId: string,
    @Param('id') id: string,
  ) {
    const invoice = await this.invoiceRepo.findById(id);
    if (!invoice || invoice.tenantId !== tenantId) throw new NotFoundException('Invoice not found');

    return {
      id: invoice.id,
      invoiceNumber: invoice.invoiceNumber,
      status: invoice.status,
      currency: invoice.currency,
      subtotal: invoice.subtotalCents / 100,
      tax: invoice.taxCents / 100,
      total: invoice.totalCents / 100,
      amountDue: invoice.amountDueCents / 100,
      periodStart: invoice.periodStart,
      periodEnd: invoice.periodEnd,
      dueDate: invoice.dueDate,
      paidAt: invoice.paidAt,
      items: [],
    };
  }

  @Post('invoices/:id/pay')
  async createPayment(
    @Headers('x-tenant-id') tenantId: string,
    @Param('id') invoiceId: string,
    @Query('provider') provider: PaymentProviderType,
    @Query('returnUrl') returnUrl?: string,
  ) {
    return this.createPaymentSession.execute({ tenantId, invoiceId, provider, returnUrl });
  }

  @Get('usage/history')
  async getUsageHistory(
    @Headers('x-tenant-id') tenantId: string,
    @Query('limit') limit = 12,
  ) {
    const history = await this.usageAggRepo.findHistoryByTenantId(tenantId, +limit);
    return history.map((u) => ({
      year: u.year,
      month: u.month,
      totalInputTokens: u.totalInputTokens,
      totalOutputTokens: u.totalOutputTokens,
      totalTokens: u.totalTokens,
      totalCostUsd: u.totalCostUsd,
      taskCount: u.taskCount,
      periodStart: u.periodStart,
      periodEnd: u.periodEnd,
    }));
  }

  @Get('providers')
  getAvailableProviders() {
    return { providers: this.providerRegistry.getAvailable() };
  }
}
