import { Capacitor } from "@capacitor/core";
import { Preferences } from "@capacitor/preferences";
import type { User } from "~/types";

export function useAuth() {
  const user = useState<User | null>("auth-user", () => null);
  const token = useState<string | null>("auth-token", () => null);
  const loading = useState<boolean>("auth-loading", () => true);

  const isNativeApp = () => process.client && Capacitor.isNativePlatform();
  const webTokenStorageKey = "auth-token";

  const persistToken = async (nextToken: string | null) => {
    if (!process.client) {
      return;
    }

    if (isNativeApp()) {
      if (nextToken) {
        await Preferences.set({ key: webTokenStorageKey, value: nextToken });
        return;
      }

      await Preferences.remove({ key: webTokenStorageKey });
      return;
    }

    if (nextToken) {
      window.localStorage.setItem(webTokenStorageKey, nextToken);
      return;
    }

    window.localStorage.removeItem(webTokenStorageKey);
  };

  const restoreToken = async () => {
    if (!process.client || token.value) {
      return;
    }

    if (isNativeApp()) {
      const storedToken = await Preferences.get({ key: webTokenStorageKey });
      token.value = storedToken.value;
      return;
    }

    token.value = window.localStorage.getItem(webTokenStorageKey);
  };

  const setSession = async (nextToken: string | null, nextUser: User | null) => {
    token.value = nextToken;
    user.value = nextUser;
    await persistToken(nextToken);
  };

  const refreshMe = async () => {
    await restoreToken();

    try {
      const me = await useApi<User>("/auth/me");
      user.value = me;
    } catch {
      await setSession(null, null);
    } finally {
      loading.value = false;
    }
  };

  const login = async (nextToken: string | null, nextUser: User) => {
    loading.value = false;
    await setSession(nextToken, nextUser);
  };

  const logout = async () => {
    const { deactivateCurrentPushSubscription, syncServiceWorkerContext } = usePush();

    await deactivateCurrentPushSubscription().catch(() => undefined);
    await useApi("/auth/logout", { method: "POST" }).catch(() => undefined);
    await setSession(null, null);
    await syncServiceWorkerContext().catch(() => undefined);
    await navigateTo("/login");
  };

  return {
    user,
    token,
    loading,
    login,
    logout,
    refreshMe
  };
}
