import { createContext, useCallback, useContext, useEffect, useState } from "react";
import { apiGet, apiPost, ApiError } from "../api/client";

const STORAGE_ACCESS = "auth_access";
const STORAGE_REFRESH = "auth_refresh";

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [accessToken, setAccessToken] = useState(() => {
    if (typeof window === "undefined") return null;
    return localStorage.getItem(STORAGE_ACCESS);
  });
  const [refreshToken, setRefreshToken] = useState(() => {
    if (typeof window === "undefined") return null;
    return localStorage.getItem(STORAGE_REFRESH);
  });
  const [loading, setLoading] = useState(true);

  const persistTokens = useCallback((access, refresh) => {
    setAccessToken(access);
    setRefreshToken(refresh);
    if (typeof window !== "undefined") {
      if (access) localStorage.setItem(STORAGE_ACCESS, access);
      else localStorage.removeItem(STORAGE_ACCESS);
      if (refresh) localStorage.setItem(STORAGE_REFRESH, refresh);
      else localStorage.removeItem(STORAGE_REFRESH);
    }
  }, []);

  const logout = useCallback(() => {
    setUser(null);
    persistTokens(null, null);
  }, [persistTokens]);

  const login = useCallback((access, refresh, userData) => {
    persistTokens(access, refresh);
    setUser(userData);
  }, [persistTokens]);

  // Restore user from token on mount
  useEffect(() => {
    if (!accessToken) {
      setLoading(false);
      return;
    }
    apiGet("/auth/me/", accessToken)
      .then((data) => {
        setUser(data);
        setLoading(false);
      })
      .catch((err) => {
        const status = ApiError && err instanceof ApiError ? err.status : err?.status;
        const message = typeof err?.message === "string" ? err.message : "";
        const isUnauthorized = status === 401 || message.includes("401");
        if (!isUnauthorized) {
          setLoading(false);
          return;
        }
        // Token invalid, try refresh
        if (!refreshToken) {
          logout();
          setLoading(false);
          return;
        }
        apiPost("/auth/token/refresh/", { refresh: refreshToken })
          .then(({ access }) => {
            persistTokens(access, refreshToken);
            return apiGet("/auth/me/", access);
          })
          .then((data) => {
            setUser(data);
          })
          .catch(() => {
            logout();
          })
          .finally(() => {
            setLoading(false);
          });
      });
  }, [accessToken, refreshToken, logout, persistTokens]);

  const value = {
    user,
    accessToken,
    loading,
    login,
    logout,
    isAuthenticated: !!user,
  };

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

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