import Stripe from "stripe";
import { BILLING_REGISTRY } from "@nextsparkjs/registries/billing-registry";
import { PlanService } from "../../services/plan.service.js";
let stripeInstance = null;
function getStripeInstance() {
  if (!stripeInstance) {
    if (!process.env.STRIPE_SECRET_KEY) {
      throw new Error("STRIPE_SECRET_KEY is not configured");
    }
    stripeInstance = new Stripe(process.env.STRIPE_SECRET_KEY, {
      apiVersion: "2025-08-27.basil",
      typescript: true
    });
  }
  return stripeInstance;
}
class StripeGateway {
  async createCheckoutSession(params) {
    const { teamId, planSlug, billingPeriod, successUrl, cancelUrl, customerEmail, customerId } = params;
    const planConfig = BILLING_REGISTRY.plans.find((p) => p.slug === planSlug);
    if (!planConfig) {
      throw new Error(`Plan ${planSlug} not found in BILLING_REGISTRY`);
    }
    const priceId = PlanService.getPriceId(planSlug, billingPeriod);
    if (!priceId) {
      throw new Error(`No price ID configured for ${planSlug} ${billingPeriod}`);
    }
    const sessionParams = {
      mode: "subscription",
      payment_method_types: ["card"],
      line_items: [{ price: priceId, quantity: 1 }],
      success_url: successUrl,
      cancel_url: cancelUrl,
      metadata: { teamId, planSlug, billingPeriod },
      client_reference_id: teamId
    };
    if (customerId) {
      sessionParams.customer = customerId;
    } else if (customerEmail) {
      sessionParams.customer_email = customerEmail;
    }
    if (planConfig.trialDays && planConfig.trialDays > 0 && !customerId) {
      sessionParams.subscription_data = {
        trial_period_days: planConfig.trialDays
      };
    }
    const session = await getStripeInstance().checkout.sessions.create(sessionParams);
    return { id: session.id, url: session.url };
  }
  async createOneTimeCheckout(params) {
    const { teamId, priceId, quantity = 1, successUrl, cancelUrl, customerEmail, customerId, metadata } = params;
    const sessionParams = {
      mode: "payment",
      payment_method_types: ["card"],
      line_items: [{ price: priceId, quantity }],
      success_url: successUrl,
      cancel_url: cancelUrl,
      metadata: { teamId, ...metadata },
      client_reference_id: teamId
    };
    if (customerId) {
      sessionParams.customer = customerId;
    } else if (customerEmail) {
      sessionParams.customer_email = customerEmail;
    }
    const session = await getStripeInstance().checkout.sessions.create(sessionParams);
    return { id: session.id, url: session.url };
  }
  async createPortalSession(params) {
    const session = await getStripeInstance().billingPortal.sessions.create({
      customer: params.customerId,
      return_url: params.returnUrl
    });
    return { url: session.url };
  }
  verifyWebhookSignature(payload, signatureOrHeaders) {
    const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
    if (!webhookSecret) {
      throw new Error("STRIPE_WEBHOOK_SECRET is not configured");
    }
    const signature = typeof signatureOrHeaders === "string" ? signatureOrHeaders : signatureOrHeaders["stripe-signature"] || "";
    const event = getStripeInstance().webhooks.constructEvent(payload, signature, webhookSecret);
    return {
      id: event.id,
      type: event.type,
      data: event.data
    };
  }
  async getCustomer(customerId) {
    const customer = await getStripeInstance().customers.retrieve(customerId);
    if ("deleted" in customer && customer.deleted) {
      throw new Error(`Customer ${customerId} has been deleted`);
    }
    return {
      id: customer.id,
      email: customer.email ?? null,
      name: customer.name ?? null
    };
  }
  async createCustomer(params) {
    const customer = await getStripeInstance().customers.create(params);
    return {
      id: customer.id,
      email: customer.email ?? null,
      name: customer.name ?? null
    };
  }
  async updateSubscriptionPlan(params) {
    var _a;
    const { subscriptionId, newPriceId, prorationBehavior = "create_prorations" } = params;
    const stripe = getStripeInstance();
    const subscription = await stripe.subscriptions.retrieve(subscriptionId);
    const itemId = (_a = subscription.items.data[0]) == null ? void 0 : _a.id;
    if (!itemId) {
      throw new Error("Subscription has no items");
    }
    const updated = await stripe.subscriptions.update(subscriptionId, {
      items: [{
        id: itemId,
        price: newPriceId
      }],
      proration_behavior: prorationBehavior
    });
    return {
      id: updated.id,
      status: updated.status,
      cancelAtPeriodEnd: updated.cancel_at_period_end
    };
  }
  async cancelSubscriptionAtPeriodEnd(subscriptionId) {
    const updated = await getStripeInstance().subscriptions.update(subscriptionId, {
      cancel_at_period_end: true
    });
    return {
      id: updated.id,
      status: updated.status,
      cancelAtPeriodEnd: updated.cancel_at_period_end
    };
  }
  async cancelSubscriptionImmediately(subscriptionId) {
    const canceled = await getStripeInstance().subscriptions.cancel(subscriptionId);
    return {
      id: canceled.id,
      status: canceled.status,
      cancelAtPeriodEnd: canceled.cancel_at_period_end
    };
  }
  getProviderName() {
    return "Stripe";
  }
  getResourceHintDomains() {
    return {
      // js.stripe.com: Stripe.js SDK loaded on page render
      preconnect: ["https://js.stripe.com"],
      // api.stripe.com: called by Stripe.js after user fills payment form (too late for preconnect)
      dnsPrefetch: ["https://api.stripe.com"]
    };
  }
  getSubscriptionDashboardUrl(externalSubscriptionId) {
    var _a;
    if (!externalSubscriptionId) return null;
    const isLive = (_a = process.env.STRIPE_SECRET_KEY) == null ? void 0 : _a.startsWith("sk_live");
    const prefix = isLive ? "" : "test/";
    return `https://dashboard.stripe.com/${prefix}subscriptions/${externalSubscriptionId}`;
  }
  async reactivateSubscription(subscriptionId) {
    const updated = await getStripeInstance().subscriptions.update(subscriptionId, {
      cancel_at_period_end: false
    });
    return {
      id: updated.id,
      status: updated.status,
      cancelAtPeriodEnd: updated.cancel_at_period_end
    };
  }
}
export {
  StripeGateway,
  getStripeInstance
};
