import {
  createContext,
  PropsWithChildren,
  useCallback,
  useContext,
  useMemo,
} from "react";
import { MantineColor, MantineColorScheme } from "@mantine/core";
import { useQueryClient } from "@tanstack/react-query";
import { Player } from "@/features/players/types";
import { playerKeys, playerQueries, useMe } from "@/features/players/queries";

interface AuthData {
  user: Player | undefined;
  metadata: { accentColor: MantineColor; colorScheme: MantineColorScheme };
  roles: string[];
  phone: string;
}

export const defaultAuthData: AuthData = {
  user: undefined,
  metadata: { accentColor: "blue", colorScheme: "auto" },
  roles: [],
  phone: ""
};

export interface AuthContextType extends AuthData {
  set: ({ user, metadata, roles }: Partial<AuthContextType>) => void;
}

const AuthContext = createContext<AuthContextType>({
  ...defaultAuthData,
  set: () => {},
});

export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
  const queryClient = useQueryClient();
  const { data } = useMe();

  const set = useCallback(
    (updates: Partial<AuthData>) => {
      queryClient.setQueryData(
        playerKeys.auth,
        (oldData: AuthData | undefined) => {
          const currentData = oldData || defaultAuthData;
          return {
            ...currentData,
            ...updates,
            metadata: updates.metadata
              ? { ...currentData.metadata, ...updates.metadata }
              : currentData.metadata,
          };
        }
      );
    },
    [queryClient]
  );

  const value = useMemo(
    () => ({
      user: data?.user || defaultAuthData.user,
      metadata: data?.metadata || defaultAuthData.metadata,
      roles: data?.roles || defaultAuthData.roles,
      phone: data?.phone || "",
      set,
    }),
    [data, defaultAuthData]
  );

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

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