import React, {
  createContext,
  useContext,
  useState,
  useCallback,
  useEffect,
  lazy,
  Suspense,
  ReactNode,
} from "react";
import { useTranslation } from "react-i18next";
import licenseService, {
  PlanTierGroup,
  LicenseInfo,
  mapLicenseToTier,
  PlanTier,
} from "@app/services/licenseService";

const StripeCheckout = lazy(() =>
  import("@app/components/shared/stripeCheckout").then((m) => ({
    default: m.StripeCheckout,
  })),
);
import { userManagementService } from "@app/services/userManagementService";
import { alert } from "@app/components/toast";
import {
  pollLicenseKeyWithBackoff,
  activateLicenseKey,
  resyncExistingLicense,
} from "@app/utils/licenseCheckoutUtils";
import { useLicense } from "@app/contexts/LicenseContext";
import { isSupabaseConfigured } from "@app/services/supabaseClient";
import { getPreferredCurrency } from "@app/utils/currencyDetection";
import {
  usePlanFeatures,
  usePlanHighlights,
} from "@app/constants/planConstants";

export interface CheckoutOptions {
  minimumSeats?: number; // Override calculated seats for enterprise
  currency?: string; // Optional currency override (auto-detected from locale)
  onSuccess?: (sessionId: string) => void; // Callback after successful payment
  onError?: (error: string) => void; // Callback on error
}

interface CheckoutContextValue {
  openCheckout: (
    tier: "server" | "enterprise",
    options?: CheckoutOptions,
  ) => Promise<void>;
  closeCheckout: () => void;
  isOpen: boolean;
  isLoading: boolean;
}

const CheckoutContext = createContext<CheckoutContextValue | undefined>(
  undefined,
);

interface CheckoutProviderProps {
  children: ReactNode;
  defaultCurrency?: string;
}

export const CheckoutProvider: React.FC<CheckoutProviderProps> = ({
  children,
  defaultCurrency,
}) => {
  const { t, i18n } = useTranslation();
  const { refetchLicense } = useLicense();
  const planFeatures = usePlanFeatures();
  const planHighlights = usePlanHighlights();
  const [isOpen, setIsOpen] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [selectedPlanGroup, setSelectedPlanGroup] =
    useState<PlanTierGroup | null>(null);
  const [minimumSeats, setMinimumSeats] = useState<number>(1);
  const [currentCurrency, setCurrentCurrency] = useState(() => {
    // Use provided default or auto-detect from locale
    return defaultCurrency || getPreferredCurrency(i18n.language);
  });
  const [currentOptions, setCurrentOptions] = useState<CheckoutOptions>({});
  const [hostedCheckoutSuccess, setHostedCheckoutSuccess] = useState<{
    isUpgrade: boolean;
    licenseKey?: string;
  } | null>(null);

  // Lazy-loaded plans state (no fetch on mount)
  const [plans, setPlans] = useState<PlanTier[]>([]);
  const [plansLoaded, setPlansLoaded] = useState(false);
  const [plansLoading, setPlansLoading] = useState(false);

  // Lazy fetch plans only when needed
  const fetchPlansIfNeeded = useCallback(
    async (currency: string) => {
      // Don't fetch if already loading
      if (plansLoading) return;

      try {
        setPlansLoading(true);
        const response = await licenseService.getPlans(
          planFeatures,
          planHighlights,
          currency,
        );
        setPlans(response.plans);
        setPlansLoaded(true);
      } catch (error) {
        console.error("Failed to fetch plans:", error);
        // Don't block - let components handle the error
      } finally {
        setPlansLoading(false);
      }
    },
    [plansLoading, planFeatures, planHighlights],
  );

  const refetchPlans = useCallback(() => {
    setPlansLoaded(false); // Force refetch
    return fetchPlansIfNeeded(currentCurrency);
  }, [currentCurrency, fetchPlansIfNeeded]);

  // Handle return from hosted Stripe checkout
  useEffect(() => {
    const handleCheckoutReturn = async () => {
      const urlParams = new URLSearchParams(window.location.search);
      const paymentStatus = urlParams.get("payment_status");
      const sessionId = urlParams.get("session_id");

      if (paymentStatus === "success" && sessionId) {
        console.log("Payment successful via hosted checkout:", sessionId);

        // Clear URL parameters
        window.history.replaceState({}, "", window.location.pathname);

        // Fetch current license info to determine upgrade vs new
        let licenseInfo: LicenseInfo | null = null;
        try {
          licenseInfo = await licenseService.getLicenseInfo();
        } catch (err) {
          console.warn("Could not fetch license info:", err);
        }

        // Check if this is an upgrade or new subscription
        // Only treat as upgrade if there's a valid PRO/ENTERPRISE license (not NORMAL/free tier)
        if (licenseInfo?.licenseType && licenseInfo.licenseType !== "NORMAL") {
          // UPGRADE: Resync existing license with Keygen
          console.log("Upgrade detected - resyncing existing license");

          const activation = await resyncExistingLicense();

          if (activation.success) {
            console.log(
              "License synced successfully, refreshing license context",
            );

            // Ensure plans are loaded before using them
            if (!plansLoaded) {
              await fetchPlansIfNeeded(currentCurrency);
            }

            // Refresh global license context
            await refetchLicense();
            await refetchPlans();

            // Determine tier from license type
            const tier =
              activation.licenseType === "ENTERPRISE" ? "enterprise" : "server";
            const planGroups = licenseService.groupPlansByTier(plans);
            const planGroup = planGroups.find((pg) => pg.tier === tier);

            if (planGroup) {
              // Reopen modal to show success
              setSelectedPlanGroup(planGroup);
              setHostedCheckoutSuccess({ isUpgrade: true });
              setIsOpen(true);
            } else {
              // Fallback to toast if plan group not found
              alert({
                alertType: "success",
                title: t("payment.upgradeSuccess"),
              });
            }
          } else {
            console.error(
              "Failed to sync license after upgrade:",
              activation.error,
            );
            alert({
              alertType: "error",
              title: t("payment.syncError"),
            });
          }
        } else {
          // NEW SUBSCRIPTION: Poll for license key
          console.log("New subscription - polling for license key");

          try {
            const installationId = await licenseService.getInstallationId();
            console.log(
              "Polling for license key with installation ID:",
              installationId,
            );

            // Use shared polling utility
            const result = await pollLicenseKeyWithBackoff(installationId);

            if (result.success && result.licenseKey) {
              // Activate the license key
              const activation = await activateLicenseKey(result.licenseKey);

              if (activation.success) {
                console.log(`License key activated: ${activation.licenseType}`);

                // Ensure plans are loaded before using them
                if (!plansLoaded) {
                  await fetchPlansIfNeeded(currentCurrency);
                }

                // Refresh global license context
                await refetchLicense();
                await refetchPlans();

                // Determine tier from license type
                const tier =
                  activation.licenseType === "ENTERPRISE"
                    ? "enterprise"
                    : "server";
                const planGroups = licenseService.groupPlansByTier(plans);
                const planGroup = planGroups.find((pg) => pg.tier === tier);

                if (planGroup) {
                  // Reopen modal to show success with license key
                  setSelectedPlanGroup(planGroup);
                  setHostedCheckoutSuccess({
                    isUpgrade: false,
                    licenseKey: result.licenseKey,
                  });
                  setIsOpen(true);
                } else {
                  // Fallback to toast if plan group not found
                  alert({
                    alertType: "success",
                    title: t("payment.licenseActivated"),
                  });
                }
              } else {
                console.error("Failed to save license key:", activation.error);
                alert({
                  alertType: "error",
                  title: t("payment.licenseSaveError"),
                });
              }
            } else if (result.timedOut) {
              console.warn("License key polling timed out");
              alert({
                alertType: "warning",
                title: t("payment.licenseDelayed"),
              });
            } else {
              console.error("License key polling failed:", result.error);
              alert({
                alertType: "error",
                title: t("payment.licensePollingError"),
              });
            }
          } catch (error) {
            console.error("Failed to poll for license key:", error);
            alert({
              alertType: "error",
              title: t("payment.licenseRetrievalError"),
            });
          }
        }
      } else if (paymentStatus === "canceled") {
        console.log("Payment canceled by user");

        // Clear URL parameters
        window.history.replaceState({}, "", window.location.pathname);

        alert({
          alertType: "warning",
          title: t("payment.paymentCanceled"),
        });
      }
    };

    handleCheckoutReturn();
  }, [
    t,
    refetchPlans,
    refetchLicense,
    plans,
    fetchPlansIfNeeded,
    plansLoaded,
    currentCurrency,
  ]);

  const openCheckout = useCallback(
    async (tier: "server" | "enterprise", options: CheckoutOptions = {}) => {
      try {
        setIsLoading(true);

        // Check if Supabase is configured
        if (!isSupabaseConfigured) {
          throw new Error(
            "Checkout is not available. Supabase is not configured.",
          );
        }

        // Update currency if provided
        const currency = options.currency || currentCurrency;
        if (currency !== currentCurrency) {
          setCurrentCurrency(currency);
        }

        // Fetch plans if not already loaded
        if (!plansLoaded) {
          await fetchPlansIfNeeded(currency);
        }

        // Fetch license info and user data for seat calculations
        let licenseInfo: LicenseInfo | null = null;
        let totalUsers = 0;

        try {
          const [licenseData, userData] = await Promise.all([
            licenseService.getLicenseInfo(),
            userManagementService.getUsers(),
          ]);

          licenseInfo = licenseData;
          totalUsers = userData.totalUsers || 0;
        } catch (err) {
          console.warn(
            "Could not fetch license/user info, proceeding with defaults:",
            err,
          );
        }

        // Calculate minimum seats for enterprise upgrades
        let calculatedMinSeats = options.minimumSeats || 1;

        if (tier === "enterprise" && !options.minimumSeats) {
          const currentTier = mapLicenseToTier(licenseInfo);

          if (currentTier === "server" || currentTier === "free") {
            // Upgrading from Server (unlimited) to Enterprise (per-seat)
            // Use current total user count as minimum
            calculatedMinSeats = Math.max(totalUsers, 1);
            console.log(
              `Setting minimum seats from server user count: ${calculatedMinSeats}`,
            );
          } else if (currentTier === "enterprise") {
            // Upgrading within Enterprise (e.g., monthly to yearly)
            // Use current licensed seat count as minimum
            calculatedMinSeats = Math.max(licenseInfo?.maxUsers || 1, 1);
            console.log(
              `Setting minimum seats from current license: ${calculatedMinSeats}`,
            );
          }
        }

        // Find the plan group for the requested tier
        const planGroups = licenseService.groupPlansByTier(plans);
        const planGroup = planGroups.find((pg) => pg.tier === tier);

        if (!planGroup) {
          throw new Error(`No ${tier} plan available`);
        }

        // Store options for callbacks
        setCurrentOptions(options);
        setMinimumSeats(calculatedMinSeats);
        setSelectedPlanGroup(planGroup);
        setIsOpen(true);
      } catch (err) {
        const errorMessage =
          err instanceof Error ? err.message : "Failed to open checkout";
        console.error("Error opening checkout:", errorMessage);
        options.onError?.(errorMessage);
      } finally {
        setIsLoading(false);
      }
    },
    [currentCurrency, plans, plansLoaded, fetchPlansIfNeeded],
  );

  const closeCheckout = useCallback(() => {
    setIsOpen(false);
    setSelectedPlanGroup(null);
    setCurrentOptions({});
    setHostedCheckoutSuccess(null);

    // Refetch plans and license after modal closes to update subscription display
    refetchPlans();
    refetchLicense();
  }, [refetchPlans, refetchLicense]);

  const handlePaymentSuccess = useCallback(
    (sessionId: string) => {
      console.log("Payment successful, session:", sessionId);
      currentOptions.onSuccess?.(sessionId);
      // Don't close modal - let user view license key and close manually
    },
    [currentOptions],
  );

  const handlePaymentError = useCallback(
    (error: string) => {
      console.error("Payment error:", error);
      currentOptions.onError?.(error);
    },
    [currentOptions],
  );

  const handleLicenseActivated = useCallback(
    (licenseInfo: {
      licenseType: string;
      enabled: boolean;
      maxUsers: number;
      hasKey: boolean;
    }) => {
      console.log("License activated:", licenseInfo);
      // Could expose this via context if needed
    },
    [],
  );

  const contextValue: CheckoutContextValue = {
    openCheckout,
    closeCheckout,
    isOpen,
    isLoading,
  };

  return (
    <CheckoutContext.Provider value={contextValue}>
      {children}

      {/* Global Checkout Modal */}
      {selectedPlanGroup && (
        <Suspense fallback={null}>
          <StripeCheckout
            opened={isOpen}
            onClose={closeCheckout}
            planGroup={selectedPlanGroup}
            minimumSeats={minimumSeats}
            onSuccess={handlePaymentSuccess}
            onError={handlePaymentError}
            onLicenseActivated={handleLicenseActivated}
            hostedCheckoutSuccess={hostedCheckoutSuccess}
          />
        </Suspense>
      )}
    </CheckoutContext.Provider>
  );
};

export const useCheckout = (): CheckoutContextValue => {
  const context = useContext(CheckoutContext);
  if (!context) {
    throw new Error("useCheckout must be used within CheckoutProvider");
  }
  return context;
};
