"use client";

import { useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import { useGeneralSettings } from "@/lib/GeneralSettingsContext";
import { useAppSelector } from "@/store/hooks";
import {
  initOneSignal,
  requestNotificationPermission,
  getPlayerId,
  loginOneSignalUser,
  logoutOneSignal,
  setUserTags,
  removeUserTags,
  storePlayerId,
} from "@/services/oneSignalService";

export function OneSignalInit(): null {
  const { settings } = useGeneralSettings();
  const { user, isAuthenticated } = useAppSelector((s) => s.auth);
  const router = useRouter();

  const initializedRef = useRef(false);
  const prevAuthRef = useRef<boolean | null>(null);
  // Snapshot of auth at init time — used for the "already logged in" case
  const authAtInitRef = useRef({ isAuthenticated, user });
  authAtInitRef.current = { isAuthenticated, user };

  useEffect(() => {
    if (!settings?.oneSignalAppId || initializedRef.current) return;

    const setup = async () => {
      try {
        await initOneSignal(settings.oneSignalAppId);
        initializedRef.current = true;

        await requestNotificationPermission();

        const { default: OneSignal } = await import("react-onesignal");

        OneSignal.Notifications.addEventListener("click", (event) => {
          const launchURL = (event as { notification: { launchURL?: string } })
            .notification?.launchURL;
          if (!launchURL) return;
          try {
            const path = new URL(launchURL).pathname;
            router.push(path);
          } catch {
            // not a valid absolute URL — skip navigation
          }
        });

        const playerId = await getPlayerId();
        if (playerId) storePlayerId(playerId);

        OneSignal.User.PushSubscription.addEventListener("change", (event) => {
          const newId = event.current.id;
          if (newId) storePlayerId(newId);
        });

        // Timing fix: if the user was already authenticated when OneSignal finished
        // initializing (i.e. login happened before OneSignal was ready), link
        // this device on the OneSignal side now so push notifications work.
        // The device_token in the login API payload may have been empty that session —
        // that's acceptable; the backend can still target this user via external_id.
        const { isAuthenticated: alreadyAuth, user: currentUser } = authAtInitRef.current;
        if (alreadyAuth && currentUser && playerId) {
          loginOneSignalUser(
            String(currentUser.id),
            settings.oneSignalAppId,
            settings.oneSignalRestKey,
          ).catch(() => {});
        }
      } catch (err) {
        console.error("[OneSignal] Initialization failed:", err);
      }
    };

    setup();
  }, [settings?.oneSignalAppId, router]);

  // Sync OneSignal user identity whenever auth state changes
  useEffect(() => {
    if (!initializedRef.current) return;
    if (prevAuthRef.current === isAuthenticated) return;
    prevAuthRef.current = isAuthenticated;

    if (isAuthenticated && user) {
      loginOneSignalUser(
        String(user.id),
        settings?.oneSignalAppId,
        settings?.oneSignalRestKey,
      ).catch(() => {});
      setUserTags({
        user_id: user.id,
        channel_id: user.channel_id,
        user_type: "registered",
      }).catch(() => {});
    } else {
      logoutOneSignal().catch(() => {});
      removeUserTags(["user_id", "channel_id", "user_type"]).catch(() => {});
    }
  }, [isAuthenticated, user]);

  return null;
}
