"use client";

import Cookies from "js-cookie";
import React, {
  createContext,
  Dispatch,
  ReactNode,
  SetStateAction,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from "react";

import { useRouter } from "next/navigation";
import { ILoginResponse, IUser, UserSchema } from "../lib/api/types";
import { COOKIE_KEYS } from "../lib/shared/cookies";

interface UserContextType {
  user: IUser | null;
  accessToken: string | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  setAuthState: (data: ILoginResponse) => void;
  logout: () => void;
  setUser: Dispatch<SetStateAction<IUser | null>>;
}

const UserContext = createContext<UserContextType | undefined>(undefined);

interface UserProviderProps {
  children: ReactNode;
}

export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
  const [user, setUser] = useState<IUser | null>(null);
  const [accessToken, setAccessToken] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const router = useRouter();

  const logout = useCallback(() => {
    setUser(null);
    setAccessToken(null);
    Cookies.remove(COOKIE_KEYS.access_token);
    Cookies.remove(COOKIE_KEYS.refresh_token);
    Cookies.remove(COOKIE_KEYS.user);
    window.location.href = "/auth/sign-in";
  }, [router]);
  useEffect(() => {
    try {
      const tokenFromCookie = Cookies.get(COOKIE_KEYS.access_token);
      const userJson = Cookies.get(COOKIE_KEYS.user);

      if (tokenFromCookie && userJson) {
        const userFromCookie = JSON.parse(userJson);
        const validation = UserSchema.safeParse(userFromCookie);
        if (validation.success) {
          setUser(validation.data);
          setAccessToken(tokenFromCookie);
        } else {
          console.warn("Invalid user data in cookie:", validation.error);
          logout();
        }
      }
    } catch (e) {
      console.error("Failed to parse user data from cookies", e);
      logout();
    } finally {
      setIsLoading(false);
    }
  }, [logout]);

  const setAuthState = useCallback((data: ILoginResponse) => {
    setAccessToken(data.access_token);
    setUser(data.user);

    Cookies.set(COOKIE_KEYS.access_token, data.access_token);
    Cookies.set(COOKIE_KEYS.refresh_token, data.refresh_token);
    Cookies.set(COOKIE_KEYS.user, JSON.stringify(data.user));
  }, []);

  const value = useMemo(
    () => ({
      user,
      accessToken,
      isAuthenticated: !!accessToken,
      isLoading,
      setAuthState,
      logout,
      setUser,
    }),
    [user, accessToken, isLoading, setAuthState, logout, setUser],
  );

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

export const useUser = (): UserContextType => {
  const context = useContext(UserContext);
  if (context === undefined) {
    throw new Error("useUser must be used within a UserProvider");
  }
  return context;
};
