import { useCallback, useEffect } from 'react';

import { DEFAULT_CURRENCY } from '@/app/(root)/account/constants';
import type { SessionStore } from '@/state/sessionStore';

// Placeholder for actual Singular SDK types if available
// You might need to install @types/singular-sdk or similar if it exists

type SingularConfig = {
  apiKey: string;
  apiSecret: string;
  productId: string;
};

declare global {
  interface Window {
    SingularConfig: any;
    singularSdk: {
      init: (config: SingularConfig) => void;
      login: (userId: string) => void;
      event: (eventName: string, eventAttributes?: Record<string, any>) => void;
      revenue: (
        eventName: string,
        currency: string,
        value: number,
        eventAttributes?: Record<string, any>
      ) => void;
      logout: () => void;
    };
  }
}

/**
 * Hook to manage Singular SDK interactions, including initialization,
 * setting user ID, and publishing events.
 * @param session - The session store containing user information.
 */
export const useSingular = (session: SessionStore) => {
  const isSingularAvailable =
    typeof window !== 'undefined' &&
    !!window.singularSdk &&
    process.env.NEXT_PUBLIC_SINGULAR_SDK_KEY &&
    process.env.NEXT_PUBLIC_SINGULAR_SDK_SECRET &&
    process.env.NEXT_PUBLIC_SINGULAR_PRODUCT_ID;

  // Initialize Singular SDK on component mount
  useEffect(() => {
    if (!isSingularAvailable) return;

    try {
      // The persistent device id is to ensure we don't generate new ids
      // for the same user for different subdomains.
      // https://support.singular.net/hc/en-us/articles/360039991491-Singular-Website-SDK-Native-Integration#Method_A_Auto-Persist_using_Cookies
      const config = new window.SingularConfig(
        process.env.NEXT_PUBLIC_SINGULAR_SDK_KEY,
        process.env.NEXT_PUBLIC_SINGULAR_SDK_SECRET,
        process.env.NEXT_PUBLIC_SINGULAR_PRODUCT_ID
      ).withAutoPersistentSingularDeviceId('suno.com');
      window.singularSdk.init(config);
    } catch (error) {
      console.error('Error initializing Singular SDK:', error);
    }
  }, [isSingularAvailable]);

  // Set Custom User ID when session or userId becomes available/changes
  useEffect(() => {
    if (!isSingularAvailable || !session.sessionIsLoaded) return;

    if (session.userId) {
      try {
        window.singularSdk.login(session.userId);
      } catch (error) {
        console.error('Error setting Singular Custom User ID:', error);
      }
    } else {
      window.singularSdk.logout();
    }
  }, [isSingularAvailable, session.sessionIsLoaded, session.userId]);

  const publishEvent = useCallback(
    (
      eventName: string,
      eventAttributes: Record<string, any> | undefined,
      eventId: string
    ) => {
      if (!isSingularAvailable) {
        console.warn(
          'Singular SDK not available, cannot publish event:',
          eventName
        );
        return;
      }
      try {
        const attributesWithId = {
          ...eventAttributes,
          eventId,
        };
        window.singularSdk.event(eventName, attributesWithId);
      } catch (error) {
        console.error(`Error publishing Singular event "${eventName}":`, error);
      }
    },
    [isSingularAvailable]
  );

  const publishRevenueEvent = useCallback(
    (
      eventName: string,
      currency: string,
      value: number,
      eventAttributes: Record<string, any> | undefined,
      eventId: string
    ) => {
      if (!isSingularAvailable) {
        console.warn(
          'Singular SDK not available, cannot publish event:',
          eventName
        );
        return;
      }
      try {
        const attributesWithId = {
          ...eventAttributes,
          eventId,
        };
        window.singularSdk.revenue(
          eventName,
          currency,
          value,
          attributesWithId
        );
      } catch (error) {
        console.error(
          `Error publishing Singular revenue event "${eventName}":`,
          error
        );
      }
    },
    [isSingularAvailable]
  );

  // Functions to publish events to Singular.
  // Full list of standard events:
  // https://support.singular.net/hc/en-us/articles/7648172966299-Singular-Standard-Events-Full-List-and-Recommended-Events-by-Vertical

  const publishSignupEvent = useCallback(
    (eventId: string) => {
      publishEvent('sng_complete_registration', undefined, eventId);
    },
    [publishEvent]
  );

  const publishSubscriptionEvent = useCallback(
    (
      subscriptionData: {
        value?: number;
        currency?: string;
        [key: string]: any;
      },
      eventId: string
    ) => {
      const eventAttributes: Record<string, any> = {};
      if (subscriptionData.subscription_id !== undefined) {
        eventAttributes.sng_attr_subscription_id =
          subscriptionData.subscription_id;
      }
      const { currency, value } = subscriptionData;
      publishRevenueEvent(
        'sng_subscribe',
        currency || DEFAULT_CURRENCY,
        value || 0,
        eventAttributes,
        eventId
      );
    },
    [publishRevenueEvent]
  );

  return {
    publishSignupEvent,
    publishSubscriptionEvent,
  };
};
