"use client";

import {
  createContext,
  useContext,
  useEffect,
  useState,
  useCallback,
  useRef,
  type ReactNode,
} from "react";
import type {
  Paddle,
  CheckoutOpenOptions,
  PaddleEventData,
} from "@paddle/paddle-js";
import { initializePaddle, CheckoutEventNames } from "@paddle/paddle-js";
import { paddleConfig } from "./paddle-config";

type CheckoutEventHandler = (event: PaddleEventData) => void;

interface PaddleContextValue {
  paddle: Paddle | null;
  isReady: boolean;
  openCheckout: (options: CheckoutOpenOptions) => void;
  onCheckoutEvent: (handler: CheckoutEventHandler) => () => void;
}

const PaddleContext = createContext<PaddleContextValue>({
  paddle: null,
  isReady: false,
  openCheckout: () => {},
  onCheckoutEvent: () => () => {},
});

export function PaddleProvider({ children }: { children: ReactNode }) {
  const [paddle, setPaddle] = useState<Paddle | null>(null);
  const [isReady, setIsReady] = useState(false);
  const listenersRef = useRef<Set<CheckoutEventHandler>>(new Set());

  useEffect(() => {
    if (!paddleConfig.clientToken) {
      console.warn("[Paddle] Missing NEXT_PUBLIC_PADDLE_CLIENT_TOKEN");
      return;
    }

    initializePaddle({
      token: paddleConfig.clientToken,
      environment: paddleConfig.environment,
      eventCallback: (event: PaddleEventData) => {
        listenersRef.current.forEach((handler) => handler(event));
      },
    })
      .then((paddleInstance) => {
        if (paddleInstance) {
          setPaddle(paddleInstance);
          setIsReady(true);
        }
      })
      .catch((err: unknown) => {
        console.error("[Paddle] Initialization failed:", err);
      });
  }, []);

  const openCheckout = useCallback(
    (options: CheckoutOpenOptions) => {
      if (!paddle) {
        console.error("[Paddle] Not initialized — cannot open checkout");
        return;
      }
      paddle.Checkout.open(options);
    },
    [paddle],
  );

  /**
   * Subscribe to Paddle checkout events.
   * Returns an unsubscribe function for cleanup.
   */
  const onCheckoutEvent = useCallback(
    (handler: CheckoutEventHandler): (() => void) => {
      listenersRef.current.add(handler);
      return () => {
        listenersRef.current.delete(handler);
      };
    },
    [],
  );

  return (
    <PaddleContext.Provider
      value={{ paddle, isReady, openCheckout, onCheckoutEvent }}
    >
      {children}
    </PaddleContext.Provider>
  );
}

/**
 * Hook to access the Paddle instance, checkout helper, and event subscription.
 */
export function usePaddle(): PaddleContextValue {
  return useContext(PaddleContext);
}

export { CheckoutEventNames };
export type { PaddleEventData };
