/** @format */

import { privateInstance } from "@/configs/axiosConfig";
import { storage } from "@/configs/storage";
import {
  AuthorizationStatus,
  getMessaging,
  getToken,
  registerDeviceForRemoteMessages,
  requestPermission,
} from "@react-native-firebase/messaging";
import { Platform } from "react-native";

const SYNCED_FCM_TOKEN_STORAGE_KEY = "@investra/synced-fcm-token";

export type PushNotificationSyncResult =
  | "synced"
  | "unchanged"
  | "unavailable"
  | "failed";

const isMessagingPermissionGranted = (status: number | null): boolean =>
  status === AuthorizationStatus.AUTHORIZED ||
  status === AuthorizationStatus.PROVISIONAL;

const requestMessagingPermission = async (): Promise<boolean> => {
  const messaging = getMessaging();
  const authStatus = await requestPermission(messaging).catch(() => null);

  return isMessagingPermissionGranted(authStatus);
};

const ensureRemoteMessagesRegistration = async (): Promise<boolean> => {
  if (Platform.OS !== "ios") {
    return true;
  }

  try {
    await registerDeviceForRemoteMessages(getMessaging());
    return true;
  } catch {
    return false;
  }
};

const getDevicePushToken = async (): Promise<string | null> => {
  const hasPermission = await requestMessagingPermission();

  if (!hasPermission) {
    return null;
  }

  const isRegistered = await ensureRemoteMessagesRegistration();

  if (!isRegistered) {
    return null;
  }

  return getToken(getMessaging()).catch(() => null);
};

export const clearPushNotificationSyncState = (): void => {
  storage.remove(SYNCED_FCM_TOKEN_STORAGE_KEY);
};

export const syncPushNotificationToken =
  async (): Promise<PushNotificationSyncResult> => {
    try {
      const deviceToken = await getDevicePushToken();

      if (!deviceToken) {
        return "unavailable";
      }

      const syncedToken = storage.getString(SYNCED_FCM_TOKEN_STORAGE_KEY);

      if (syncedToken === deviceToken) {
        return "unchanged";
      }

      await privateInstance.post("/client/notification/token-update", {
        token: deviceToken,
      });
      storage.set(SYNCED_FCM_TOKEN_STORAGE_KEY, deviceToken);

      return "synced";
    } catch (error) {
      console.warn("Error syncing push notification token:", error);
      return "failed";
    }
  };
