import { createContext, useCallback, useContext, useEffect, useState } from "react";
import {
  apiLogin,
  apiMe,
  clearSession,
  getStoredUser,
  getToken,
  setSession,
  type NadiUser,
} from "@/lib/nadiAuth";
import { clearManagedProfile } from "@/hooks/useSubscriberProfileSync";
import { purgeOtherUserProfiles } from "@/hooks/useProfiles";
import { clearUserData } from "@/lib/clearUserData";

type AuthState = {
  user: NadiUser | null;
  isGuest: boolean;
  loading: boolean;
  login: (username: string, password: string) => Promise<NadiUser>;
  logout: () => void;
  continueAsGuest: () => void;
  refresh: () => Promise<void>;
};

const GUEST_KEY = "nadi_is_guest";

const AuthCtx = createContext<AuthState | undefined>(undefined);

export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
  const [user, setUser] = useState<NadiUser | null>(() => getStoredUser());
  const [isGuest, setIsGuest] = useState<boolean>(() => {
    try {
      return localStorage.getItem(GUEST_KEY) === "1";
    } catch (e) {
      console.warn("[useAuth] read guest flag failed", e);
      return false;
    }
  });
  const [loading, setLoading] = useState<boolean>(() => !!getToken() && !getStoredUser());

  // Validate stored token on mount
  useEffect(() => {
    const t = getToken();
    if (!t) {
      setLoading(false);
      return;
    }
    let cancelled = false;
    apiMe()
      .then((u) => {
        if (!cancelled) setUser(u);
      })
      .catch((e) => {
        console.warn("[useAuth] token validation failed", e);
        if (!cancelled) {
          clearSession();
          setUser(null);
        }
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  const login = useCallback(async (username: string, password: string) => {
    let res: { access_token: string; user: NadiUser };
    try {
      res = await apiLogin(username, password);
    } catch (apiErr) {
      console.error("[useAuth] apiLogin failed:", apiErr);
      throw apiErr; // re-throw so Login.tsx shows the error
    }
    // Validate response shape before using it
    if (!res || !res.access_token || !res.user || !res.user.id) {
      throw new Error("Invalid login response from server");
    }
    try {
      setSession(res.access_token, res.user);
      setUser(res.user);
    } catch (storeErr) {
      console.error("[useAuth] session storage failed:", storeErr);
      // Still set user in memory even if localStorage fails
      setUser(res.user);
    }
    try {
      localStorage.removeItem(GUEST_KEY);
    } catch (e) {
      console.warn("[useAuth] clear guest flag failed", e);
    }
    setIsGuest(false);
    // Purge IndexedDB profiles owned by a DIFFERENT user so a new
    // account always starts with an empty "Owned" list (BUG-7 FIX).
    try {
      await purgeOtherUserProfiles(res.user.id);
    } catch (e) {
      console.warn("[useAuth] purgeOtherUserProfiles failed", e);
    }
    // If admin signs in, wipe any leftover subscriber-managed profile from a previous session.
    try {
      if (res.user.role !== "user") clearManagedProfile();
    } catch (e) {
      console.warn("[useAuth] clearManagedProfile failed", e);
    }
    // Broadcast profile change so the UI re-reads the filtered lists.
    try {
      window.dispatchEvent(new Event("nadiplay-profiles-changed"));
    } catch { /* noop */ }
    return res.user;
  }, []);

  const logout = useCallback(() => {
    clearManagedProfile();
    clearSession();
    setUser(null);
    try {
      localStorage.removeItem(GUEST_KEY);
    } catch (e) {
      console.warn("[useAuth] clear guest flag failed", e);
    }
    setIsGuest(false);
    // BUG FIX (iter-5): wipe every piece of user-scoped data the app
    // has stashed on the device — Xtream playlists (IndexedDB), the
    // active-profile breadcrumb, favorites, ad-free state, the native
    // "last played" channel — so the next user signing in on the same
    // device starts with a completely clean slate.
    // Fire-and-forget: synchronous logout UX shouldn't block on async
    // IDB / Capacitor calls. Failures are logged inside clearUserData.
    void clearUserData();
    // BUG-7 FIX: broadcast profile change so UI re-reads filtered lists.
    try {
      window.dispatchEvent(new Event("nadiplay-profiles-changed"));
    } catch { /* noop */ }
  }, []);

  const continueAsGuest = useCallback(() => {
    clearManagedProfile();
    try {
      localStorage.setItem(GUEST_KEY, "1");
    } catch (e) {
      console.warn("[useAuth] set guest flag failed", e);
    }
    setIsGuest(true);
    // BUG-7 FIX: broadcast profile change so UI re-reads filtered lists.
    try {
      window.dispatchEvent(new Event("nadiplay-profiles-changed"));
    } catch { /* noop */ }
  }, []);

  const refresh = useCallback(async () => {
    if (!getToken()) return;
    try {
      const u = await apiMe();
      setUser(u);
    } catch (e) {
      console.warn("[useAuth] refresh failed", e);
      clearSession();
      setUser(null);
    }
  }, []);

  return (
    <AuthCtx.Provider value={{ user, isGuest, loading, login, logout, continueAsGuest, refresh }}>
      {children}
    </AuthCtx.Provider>
  );
};

export const useAuth = (): AuthState => {
  const ctx = useContext(AuthCtx);
  if (!ctx) throw new Error("useAuth must be used inside <AuthProvider>");
  return ctx;
};
