import type Stripe from "stripe";
import { STRIPE_PRODUCT_TAX_CODE } from "@/lib/credits";
import { prisma } from "@/lib/db";
import { getStripe } from "@/lib/stripe";

/** Enable Stripe Tax only when Dashboard registrations are active (STRIPE_AUTOMATIC_TAX=true). */
export function isStripeAutomaticTaxEnabled(): boolean {
  return process.env.STRIPE_AUTOMATIC_TAX === "true";
}

/**
 * Shared Checkout Session options required/recommended by Stripe for SaaS:
 * - client_reference_id for linking
 * - automatic_tax (opt-in) + customer_update.address when tax is on
 * - tax_code already set on product_data by callers
 */
export function checkoutTaxAndReferenceOptions(userId: string): Partial<Stripe.Checkout.SessionCreateParams> {
  const opts: Partial<Stripe.Checkout.SessionCreateParams> = {
    client_reference_id: userId,
  };

  if (isStripeAutomaticTaxEnabled()) {
    opts.automatic_tax = { enabled: true };
    opts.customer_update = { address: "auto", name: "auto" };
    // Collect billing address so tax can be calculated for new/returning customers
    opts.billing_address_collection = "required";
  }

  return opts;
}

/** tax_behavior required on Prices when automatic tax is enabled. */
export function priceDataTaxFields(): { tax_behavior?: Stripe.Checkout.SessionCreateParams.LineItem.PriceData["tax_behavior"] } {
  if (!isStripeAutomaticTaxEnabled()) return {};
  // Exclusive: listed prices are pre-tax; VAT/GST added at checkout
  return { tax_behavior: "exclusive" };
}

export function productDataWithTaxCode(
  name: string,
  description: string,
): Stripe.Checkout.SessionCreateParams.LineItem.PriceData.ProductData {
  return {
    name,
    description,
    tax_code: STRIPE_PRODUCT_TAX_CODE,
  };
}

/** Ensure the app user has a Stripe Customer and return its id. */
export async function ensureStripeCustomer(userId: string, email: string): Promise<string> {
  const dbUser = await prisma.user.findUniqueOrThrow({
    where: { id: userId },
    select: { stripeCustomerId: true },
  });

  if (dbUser.stripeCustomerId) return dbUser.stripeCustomerId;

  const stripe = getStripe();
  const customer = await stripe.customers.create({
    email,
    metadata: { userId },
  });

  await prisma.user.update({
    where: { id: userId },
    data: { stripeCustomerId: customer.id },
  });

  return customer.id;
}
