import Stripe from "stripe";

export interface StripeWebhookConfig {
  secret: string;
  apiVersion?: string;
}

export interface StripeDashboardConfig {
  publishableKey: string;
  secretKey: string;
  webhookSecret: string;
  apiVersion?: string;
}

type StripeEvent =
  | "customer.created"
  | "customer.updated"
  | "customer.deleted"
  | "subscription.created"
  | "subscription.updated"
  | "subscription.deleted"
  | "invoice.created"
  | "invoice.payment_succeeded"
  | "invoice.payment_failed"
  | "payment_intent.created"
  | "payment_intent.succeeded"
  | "payment_intent.payment_failed"
  | "checkout.session.completed"
  | "product.created"
  | "product.updated"
  | "price.created"
  | "price.updated";

export class StripeService {
  private stripe: Stripe;
  private webhookSecret: string;
  private initialized: boolean = false;

  constructor(config: StripeDashboardConfig) {
    this.stripe = new Stripe(config.secretKey, {
      apiVersion: config.apiVersion || "2024-12-18.acacia",
    });
    this.webhookSecret = config.webhookSecret;
    this.initialized = true;
  }

  async initialize(): Promise<void> {
    // Verify connection by fetching account
    const account = await this.stripe.account.retrieve();
    this.initialized = !!account.id;
  }

  async createCustomer(email: string, name?: string, metadata?: Record<string, string>): Promise<Stripe.Customer> {
    return await this.stripe.customers.create({
      email,
      name,
      metadata,
    });
  }

  async createSubscription(customerId: string, priceId: string): Promise<Stripe.Subscription> {
    return await this.stripe.subscriptions.create({
      customer: customerId,
      items: [{ price: priceId }],
    });
  }

  async createCheckoutSession(
    customerId: string,
    priceId: string,
    successUrl: string,
    cancelUrl: string
  ): Promise<Stripe.Checkout.Session> {
    return await this.stripe.checkout.sessions.create({
      customer: customerId,
      line_items: [{ price: priceId, quantity: 1 }],
      mode: "subscription",
      success_url: successUrl,
      cancel_url: cancelUrl,
    });
  }

  async verifyWebhook(payload: Buffer, signature: string): Promise<Stripe.Event> {
    return await this.stripe.webhooks.constructEventAsync(payload, signature, this.webhookSecret);
  }

  handleWebhookEvent(event: Stripe.Event): void {
    switch (event.type) {
      case "customer.created":
        console.log("Customer created:", (event.data.object as Stripe.Customer).email);
        break;
      case "subscription.created":
        console.log("Subscription created:", (event.data.object as Stripe.Subscription).id);
        break;
      case "invoice.payment_succeeded":
        console.log("Payment succeeded:", (event.data.object as Stripe.Invoice).id);
        break;
      case "invoice.payment_failed":
        console.log("Payment failed:", (event.data.object as Stripe.Invoice).id);
        break;
      case "payment_intent.succeeded":
        console.log("Payment intent succeeded:", (event.data.object as Stripe.PaymentIntent).id);
        break;
      case "payment_intent.payment_failed":
        console.log("Payment intent failed:", (event.data.object as Stripe.PaymentIntent).id);
        break;
      case "checkout.session.completed":
        console.log("Checkout session completed:", (event.data.object as Stripe.Checkout.Session).id);
        break;
      default:
        console.log(`Unhandled event type: ${event.type}`);
    }
  }

  async listCustomers(limit?: number): Promise<Stripe.ApiList<Stripe.Customer>> {
    return await this.stripe.customers.list({ limit: limit || 10 });
  }

  async getCustomer(customerId: string): Promise<Stripe.Customer> {
    return await this.stripe.customers.retrieve(customerId);
  }

  async updateCustomer(
    customerId: string,
    updates: { email?: string; name?: string; metadata?: Record<string, string> }
  ): Promise<Stripe.Customer> {
    return await this.stripe.customers.update(customerId, updates);
  }

  async deleteCustomer(customerId: string): Promise<Stripe.Customer> {
    return await this.stripe.customers.del(customerId);
  }

  getDashboardUrl(): string {
    return "https://dashboard.stripe.com";
  }

  getWebhookEndpointUrl(): string {
    return `/api/webhooks/stripe`;
  }
}

export const createStripeService = (config: StripeDashboardConfig): StripeService => {
  return new StripeService(config);
};
