import {
  createContext,
  useContext,
  type ReactNode,
} from "react";
import axios from "axios";
import { useQuery } from "@tanstack/react-query";

import { client, type ContextMe } from "@/client";

type AuthContextValue = {
  me: ContextMe | null;
  user: ContextMe | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  error: Error | null;
  refresh: () => Promise<ContextMe | null>;
};

const AuthContext = createContext<AuthContextValue | null>(null);

async function fetchMe() {
  try {
    const response = await client.authMe();
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error) && error.response?.status === 401) {
      return null;
    }

    throw error;
  }
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const { data, error, isLoading, refetch } = useQuery({
    queryKey: ["auth", "me"],
    queryFn: fetchMe,
    retry: false,
  });

  const me = data ?? null;

  return (
    <AuthContext.Provider
      value={{
        me,
        user: me,
        isAuthenticated: me !== null,
        isLoading,
        error,
        refresh: async () => {
          const result = await refetch();
          return result.data ?? null;
        },
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);

  if (!context) {
    throw new Error("useAuth must be used within AuthProvider.");
  }

  return context;
}
