import { createContext, useContext, useSyncExternalStore } from "react";
import {
  onAuthStateChanged,
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  signOut,
  sendEmailVerification as firebaseSendEmailVerification,
} from "firebase/auth";
import { auth } from "../firebase/config";
import { getAccount } from "../api/account";

const AuthContext = createContext(undefined);

const DEFAULT_TIER_LIMITS = {
  max_addresses: 1,
  max_alert_types: 1,
  allowed_channels: ["email"],
};

// External auth store - lives outside React
const createAuthStore = () => {
  let state = {
    currentUser: null,
    userTier: "free",
    tierLimits: DEFAULT_TIER_LIMITS,
    isSubscribed: false,
    loading: true,
  };
  const listeners = new Set();

  const notify = () => listeners.forEach((fn) => fn());

  const setState = (partial) => {
    state = { ...state, ...partial };
    notify();
  };

  const fetchAccount = async () => {
    try {
      const data = await getAccount();
      setState({
        userTier: data.subscription_tier || "free",
        tierLimits: data.tier_limits || DEFAULT_TIER_LIMITS,
        isSubscribed:
          data.subscription_status === "active" ||
          data.subscription_status === "trialing",
      });
    } catch {
      setState({ isSubscribed: false });
    }
  };

  // Set up Firebase listener once, outside of React
  onAuthStateChanged(auth, async (user) => {
    setState({ loading: true, currentUser: user });
    if (user) {
      await fetchAccount();
    } else {
      setState({ isSubscribed: false, userTier: "free", tierLimits: DEFAULT_TIER_LIMITS });
    }
    setState({ loading: false });
  });

  return {
    subscribe: (listener) => {
      listeners.add(listener);
      return () => listeners.delete(listener);
    },
    getSnapshot: () => state,
    refreshAccount: fetchAccount,
  };
};

const authStore = createAuthStore();

export function AuthProvider({ children }) {
  const state = useSyncExternalStore(authStore.subscribe, authStore.getSnapshot);

  const signup = (email, password) => createUserWithEmailAndPassword(auth, email, password);
  const login = (email, password) => signInWithEmailAndPassword(auth, email, password);
  const logout = () => signOut(auth);

  const sendEmailVerification = () => {
    if (auth.currentUser) {
      return firebaseSendEmailVerification(auth.currentUser);
    }
  };

  const reloadUser = async () => {
    if (auth.currentUser) {
      await auth.currentUser.reload();
      return auth.currentUser;
    }
    return null;
  };

  const value = {
    ...state,
    signup,
    login,
    logout,
    sendEmailVerification,
    reloadUser,
    refreshAccount: authStore.refreshAccount,
  };

  return (
    <AuthContext.Provider value={value}>
      {!state.loading && children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

export default useAuth;
