import { Analytics, AnalyticsBrowser } from "@segment/analytics-next";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { AnalyticsContext } from "./context";
import { AnalyticsContextValue } from "./types";

export interface AnalyticsProviderProps {
  segmentWriteToken?: string;
  blockedUserAgents?: string[];
}

export const AnalyticsProvider = ({
  segmentWriteToken,
  blockedUserAgents,
  children,
}: React.PropsWithChildren<AnalyticsProviderProps>) => {
  const [isReady, setIsReady] = useState(false);

  const isBlockedUserAgent = useMemo(() => {
    return (
      !!blockedUserAgents &&
      typeof window !== "undefined" &&
      !!window?.navigator?.userAgent &&
      blockedUserAgents.includes(window?.navigator?.userAgent)
    );
  }, [blockedUserAgents?.join("")]);

  const analytics = useMemo(() => {
    if (!segmentWriteToken) return;
    return AnalyticsBrowser.load({ writeKey: segmentWriteToken });
  }, [segmentWriteToken]);

  useEffect(() => {
    if (!analytics) return;
    analytics.ready(() => setIsReady(true));
  }, [analytics]);

  const identify = useCallback(
    (...args: Parameters<Analytics["identify"]>) => {
      if (!analytics || isBlockedUserAgent) return;
      analytics.identify(...args);
    },
    [analytics, isBlockedUserAgent]
  );

  const alias = useCallback(
    (...args: Parameters<Analytics["alias"]>) => {
      if (!analytics) return;
      analytics.alias(...args);
    },
    [analytics]
  );

  const trackPageView = useCallback(
    (...args: Parameters<Analytics["page"]>) => {
      if (!analytics) return;
      analytics.page(...args);
    },
    [analytics]
  );

  const track = useCallback(
    (...args: Parameters<Analytics["track"]>) => {
      if (!analytics || isBlockedUserAgent) return;
      analytics.track(...args);
    },
    [analytics, isBlockedUserAgent]
  );

  const reset = useCallback(() => {
    if (!analytics) return;
    analytics.reset();
  }, [analytics]);

  const contextValue: AnalyticsContextValue = {
    analytics,
    analyticsReady: isReady,
    identify,
    alias,
    trackPageView,
    track,
    reset,
  };

  const value: AnalyticsContextValue = useMemo(
    () => contextValue,
    [...Object.values(contextValue)]
  );

  return (
    <AnalyticsContext.Provider value={value}>
      {children}
    </AnalyticsContext.Provider>
  );
};
