import { NextRequest, NextResponse } from 'next/server';
import { getSession } from '@/lib/auth';
import { stripe } from '@/lib/stripe';
import { getOrCreateStripeCustomer } from '@/lib/billing-service';
import type Stripe from 'stripe';
import { db, schema } from '@/lib/db';
import { eq } from 'drizzle-orm';

/**
 * GET /api/billing/status
 * Returns whether the user has a valid payment method on file.
 * Used to enforce mandatory payment method requirement.
 */
export async function GET(request: NextRequest) {
  const accessToken = request.cookies.get('scriba.access_token')?.value;
  const session = await getSession(accessToken);
  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // Admins are exempt from payment requirements
  const user = await db.query.users.findFirst({
    where: eq(schema.users.id, session.user.id),
    columns: { role: true },
  });

  // Company suspension status applies to every member (owner and non-owner).
  const sessionCompanyId = (session.user as { companyId?: string | null }).companyId ?? null;
  const suspendedCompany = sessionCompanyId
    ? await db.query.companies.findFirst({
        where: eq(schema.companies.id, sessionCompanyId),
        columns: { suspendedAt: true, suspendedReason: true },
      })
    : null;
  const companySuspended = Boolean(suspendedCompany?.suspendedAt);
  const suspensionReason = suspendedCompany?.suspendedReason ?? null;

  if (user?.role === 'admin') {
    return NextResponse.json({
      hasPaymentMethod: true,
      hasRequiredFinancialData: true,
      requirementsComplete: true,
      isAdmin: true,
      customerId: null,
      paymentMethodsCount: 0,
      companySuspended: false,
      suspensionReason: null,
    });
  }

  try {
    const customerId = await getOrCreateStripeCustomer(
      session.user.id,
      session.user.email,
      session.user.name,
    );

    // Check for saved Stripe payment methods (including PayPal if enabled in Stripe)
    const [cards, sepaDebits, paypals, links] = await Promise.all([
      stripe.paymentMethods.list({ customer: customerId, type: 'card' }).catch(() => ({ data: [] })),
      stripe.paymentMethods.list({ customer: customerId, type: 'sepa_debit' }).catch(() => ({ data: [] })),
      stripe.paymentMethods.list({ customer: customerId, type: 'paypal' }).catch(() => ({ data: [] })),
      stripe.paymentMethods.list({ customer: customerId, type: 'link' }).catch(() => ({ data: [] })),
    ]);
    const paymentMethodsCount = cards.data.length + sepaDebits.data.length + paypals.data.length + links.data.length;

    // Also check customer default payment method
    const customer = await stripe.customers.retrieve(customerId) as Stripe.Customer;
    const defaultPmId = !customer.deleted
      ? (typeof customer.invoice_settings?.default_payment_method === 'string'
          ? customer.invoice_settings.default_payment_method
          : (customer.invoice_settings?.default_payment_method as Stripe.PaymentMethod | null)?.id ?? null)
      : null;

    const hasPaymentMethod = paymentMethodsCount > 0 || !!defaultPmId;
    const ownerRecord = await db.query.users.findFirst({
      where: eq(schema.users.id, session.user.id),
      columns: { companyId: true, isOwner: true },
    });
    const company = ownerRecord?.companyId
      ? await db.query.companies.findFirst({
          where: eq(schema.companies.id, ownerRecord.companyId),
          columns: { financialData: true },
        })
      : null;
    const financialData = (company?.financialData ?? {}) as {
      billingAddress?: string;
      billingEmail?: string;
    };
    const hasRequiredFinancialData = ownerRecord?.isOwner
      ? Boolean(financialData.billingAddress?.trim() && financialData.billingEmail?.trim())
      : true;
    const requirementsComplete = ownerRecord?.isOwner
      ? hasPaymentMethod && hasRequiredFinancialData
      : hasPaymentMethod;

    return NextResponse.json({
      hasPaymentMethod,
      hasRequiredFinancialData,
      requirementsComplete,
      customerId,
      paymentMethodsCount,
      companySuspended,
      suspensionReason,
    });
  } catch (err) {
    console.error('Billing status check error:', err);
    // Stripe may be unreachable/misconfigured. Never hard-fail here: company
    // suspension is a DB fact and must stay authoritative, and a payment-provider
    // blip must not lock members or owners out of the app. Degrade gracefully.
    return NextResponse.json({
      hasPaymentMethod: true,
      hasRequiredFinancialData: true,
      requirementsComplete: true,
      paymentStatusUnknown: true,
      customerId: null,
      paymentMethodsCount: 0,
      companySuspended,
      suspensionReason,
    });
  }
}
