import { useEffect, useRef, useCallback } from "react";
import { Platform } from "react-native";
import * as Notifications from "expo-notifications";
import * as Device from "expo-device";
import { useAuth } from "@clerk/clerk-expo";
import { savePushToken } from "../api/notifications";
import log from "../utils/logger";

// Configure notification behavior
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
    shouldShowBanner: true,
    shouldShowList: true,
  }),
});

/**
 * Hook to register for push notifications and save the token
 */
export function useNotificationPermissions() {
  const { getToken, isSignedIn } = useAuth();
  const notificationListener = useRef<Notifications.Subscription | undefined>(
    undefined,
  );
  const responseListener = useRef<Notifications.Subscription | undefined>(
    undefined,
  );

  const registerForPushNotifications = useCallback(async () => {
    try {
      // Only works on physical devices (not simulators/emulators)
      if (!Device.isDevice) {
        log.warn("Push notifications only work on physical devices");
        return;
      }

      // Check existing permissions
      // @ts-ignore - expo-notifications type mismatch
      const { status: existingStatus } =
        await Notifications.getPermissionsAsync();

      let finalStatus = existingStatus;

      // Request permissions if not already granted
      if (existingStatus !== "granted") {
        // @ts-ignore - expo-notifications type mismatch
        const { status } = await Notifications.requestPermissionsAsync();
        finalStatus = status;
      }

      if (finalStatus !== "granted") {
        log.warn("Failed to get push notification permissions");
        return;
      }

      // Get the Expo push token
      const expoPushToken = (await Notifications.getExpoPushTokenAsync()).data;

      log.info("Expo push token obtained", {
        tokenPrefix: expoPushToken.substring(0, 20) + "...",
      });

      // Determine device type
      const deviceType = Platform.OS === "ios" ? "ios" : "android";

      // Save token to backend
      const authToken = await getToken();
      await savePushToken(expoPushToken, deviceType, authToken);

      log.info("Push token saved to backend", { deviceType });

      // Configure Android notification channel
      if (Platform.OS === "android") {
        await Notifications.setNotificationChannelAsync("default", {
          name: "default",
          importance: Notifications.AndroidImportance.MAX,
          vibrationPattern: [0, 250, 250, 250],
          lightColor: "#FF231F7C",
        });
      }
    } catch (error) {
      // In Expo Go, remote push notifications are not available (removed in SDK 53)
      // This is expected and doesn't affect in-app notifications
      if (!Device.isDevice || __DEV__) {
        log.info(
          "Push notification registration skipped (Expo Go or development mode)",
          { error: error instanceof Error ? error.message : String(error) },
        );
      } else {
        log.error("Failed to register for push notifications", error);
      }
    }
  }, [getToken]);

  useEffect(() => {
    if (!isSignedIn) return;

    // Register for push notifications
    registerForPushNotifications();

    // Listener for notifications received while app is foregrounded
    notificationListener.current =
      Notifications.addNotificationReceivedListener((notification) => {
        log.debug("Notification received in foreground", {
          title: notification.request.content.title,
        });
      });

    // Listener for when user taps on a notification
    responseListener.current =
      Notifications.addNotificationResponseReceivedListener((response) => {
        log.debug("Notification tapped", {
          data: response.notification.request.content.data,
        });
        // TODO: Handle navigation based on notification type
      });

    return () => {
      notificationListener.current?.remove();
      responseListener.current?.remove();
    };
  }, [isSignedIn, registerForPushNotifications]);
}
