/**
 * GET /api/billing/invoices
 * Retrieve user's Stripe invoices with billing history
 *
 * Security:
 * - Authentication required
 * - Only returns invoices for authenticated user
 * - Rate limited to prevent abuse
 *
 * Features:
 * - Fetches invoices from Stripe
 * - Merges with billing_history from Supabase
 * - Provides payment summary
 * - Supports pagination and filtering
 */

import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { PRICING_TIERS } from "@/lib/config/pricing-tiers";
import { stripe } from "@/lib/stripe";
import { convexQuery } from "@/lib/convex-client";
export async function GET() {
  try {
    // Authenticate user
    const session = await auth();

    const activeSubscription = await convexQuery<Record<string, unknown>>(
      "billing/queries:getActiveSubscription",
      { userId: user.id },
    );

    const stripeCustomerId =
      user.stripeCustomerId ||
      ((activeSubscription?.stripeCustomerId as string | undefined) ?? null);

    if (!stripeCustomerId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const { searchParams } = new URL(request.url);
    const limit = Math.min(
      parseInt(searchParams.get("limit") || "10", 10),
      100,
    );
    const status = searchParams.get("status") as
      | "paid"
      | "open"
      | "void"
      | "uncollectible"
      | null;

    const invoicesResponse = await stripe.invoices.list({
      customer: stripeCustomerId,
      limit,
      ...(status ? { status } : {}),
    });

    const billingHistory =
      (await convexQuery<Array<Record<string, unknown>>>(
        "billing/queries:getBillingHistory",
        {
          customerId: stripeCustomerId,
          limit,
        },
      )) ?? [];

    const formattedInvoices = invoicesResponse.data.map((invoice) => ({
      id: invoice.id,
      number: invoice.number,
      date: new Date(invoice.created * 1000).toISOString(),
      dueDate: invoice.due_date
        ? new Date(invoice.due_date * 1000).toISOString()
        : null,
      amount: invoice.amount_paid / 100,
      amountDue: invoice.amount_due / 100,
      currency: invoice.currency.toUpperCase(),
      status: invoice.status,
      pdfUrl: invoice.invoice_pdf,
      hostedUrl: invoice.hosted_invoice_url,
      description: invoice.description || "Subscription payment",
      periodStart: invoice.period_start
        ? new Date(invoice.period_start * 1000).toISOString()
        : null,
      periodEnd: invoice.period_end
        ? new Date(invoice.period_end * 1000).toISOString()
        : null,
      subscriptionId:
        typeof invoice.subscription === "string"
          ? invoice.subscription
          : (invoice.subscription?.id ?? null),
    }));

    const totalPaid = invoicesResponse.data
      .filter((invoice) => invoice.status === "paid")
      .reduce((sum, invoice) => sum + invoice.amount_paid / 100, 0);

    const lastPayment = invoicesResponse.data.find(
      (invoice) => invoice.status === "paid",
    );

    const summary = {
      totalPaid: Math.round(totalPaid * 100) / 100,
      invoiceCount: invoicesResponse.data.length,
      lastPayment: lastPayment
        ? {
            amount: lastPayment.amount_paid / 100,
            date: new Date(lastPayment.created * 1000).toISOString(),
            invoiceNumber: lastPayment.number,
          }
        : null,
      nextBilling: activeSubscription
        ? {
            amount: getSubscriptionAmount(
              activeSubscription.tierId as string | undefined,
              activeSubscription.billingPeriod as string | undefined,
            ),
            date: new Date(
              Number(activeSubscription.currentPeriodEnd || Date.now()),
            ).toISOString(),
            status: String(activeSubscription.status || "active"),
          }
        : null,
    };

    return NextResponse.json({
      hasInvoices: invoicesResponse.data.length > 0,
      invoices: formattedInvoices,
      billingHistory: billingHistory.map((item) => ({
        id: item.prismaId ?? item._id,
        event: item.event,
        amount: item.amount,
        currency: item.currency,
        createdAt: item.createdAt
          ? new Date(item.createdAt as number).toISOString()
          : null,
        metadata: item.metadata ?? null,
        invoiceId: item.invoiceId ?? null,
      })),
      summary,
      meta: {
        count: invoicesResponse.data.length,
        hasMore: invoicesResponse.has_more,
        limit,
      },
    });
    if (payments !== null) {
      return NextResponse.json({ payments, success: true });
    }
  } catch (error: unknown) {
    console.error("Error fetching invoices:", error);

    const err = error as { type?: string; message?: string };

    // Handle specific Stripe errors
    if (err.type === "StripeInvalidRequestError") {
      return NextResponse.json(
        { error: "Invalid request to Stripe", message: err.message },
        { status: 400 },
      );
    }

    if (err.type === "StripeAPIError") {
      return NextResponse.json(
        {
          error: "Stripe service unavailable",
          message: "Please try again later",
        },
        { status: 503 },
      );
    }

    return NextResponse.json(
      { error: "Internal server error", message: err.message },
      { status: 500 },
    );
  }
}
