import React, {
    createContext,
    useContext,
    useState,
    useMemo,
    useEffect,
  } from "react";
  import PropTypes from "prop-types";
  const decodeJwtPayload = (token) =>
    JSON.parse(atob(token.split(".")[1]));

  const AuthContext = createContext();

  const AuthProvider = ({ children }) => {
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
      const fetchData = async () => {
        const jwtToken = localStorage.getItem("token");

        if (jwtToken) {
          try {
            const decodedPayload = decodeJwtPayload(jwtToken);
            const res = await fetch(
              `${import.meta.env.VITE_BACKEND_URL}/api/users/${decodedPayload.user}`,
              {
                headers: { "x-auth-token": jwtToken },
              }
            );
            if (!res.ok) throw new Error("Failed to fetch user");
            const data = await res.json();
            setUser(data);
          } catch (error) {
            console.error("Error fetching user data:", error);
            localStorage.removeItem("token");
          } finally {
            setLoading(false);
          }
        } else {
          setLoading(false);
        }
      };

      fetchData();
    }, []);

    const loginWithOAuth = async (token) => {
      const res = await fetch(
        `${import.meta.env.VITE_BACKEND_URL}/api/auth/callback?code=${encodeURIComponent(token)}`
      );
      const data = await res.json();

      if (!res.ok) {
        throw new Error(data.message || "OAuth login failed");
      }

      localStorage.setItem("token", data.token);
      setUser(data.user);
      return data.user;
    };

    const logout = () => {
      localStorage.removeItem("token");
      setUser(null);
    };

    const editUser = async (updatedFields) => {
      try {
        const response = await fetch(
          `${import.meta.env.VITE_BACKEND_URL}/api/users/${user.id}`,
          {
            method: "PUT",
            headers: {
              "Content-Type": "application/json",
              "x-auth-token": localStorage.getItem("token"),
            },
            body: JSON.stringify(updatedFields),
          }
        );

        if (response.ok) {
          const updatedUser = await response.json();
          setUser((prevUser) => ({
            ...prevUser,
            ...updatedUser.user,
          }));
          return "User updated successfully";
        }
        if (response.status === 400) {
          console.error("Bad Request:", response.statusText);
          throw new Error("Bad Request");
        } else if (response.status === 401) {
          console.error("Unauthorized:", response.statusText);
          throw new Error("Unauthorized");
        } else {
          console.error("Error updating user:", response.statusText);
          throw new Error("Error updating user");
        }
      } catch (error) {
        console.error("Error updating user:", error);
        throw new Error("An error occurred during user update");
      }
    };

    const sendPasswordResetEmail = async (email) => {
      try {
        const response = await fetch(
          `${import.meta.env.VITE_BACKEND_URL}/api/forgot-password`,
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({ mail: email }),
          }
        );

        if (response.ok) {
          return "Password reset email sent successfully";
        }

        const data = await response.json();
        throw new Error(data.message || "Error sending password reset email");
      } catch (error) {
        console.error("Error sending password reset email:", error);
        throw new Error(
          "An error occurred while sending the password reset email"
        );
      }
    };

    const authContextValue = useMemo(() => {
      return {
        user,
        loading,
        logout,
        loginWithOAuth,
        editUser,
        sendPasswordResetEmail,
        setUser: (newUser) => {
          setUser(newUser);
        },
      };
    }, [user, loading, logout]);

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

  AuthProvider.propTypes = {
    children: PropTypes.node.isRequired,
  };

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

  export { AuthProvider, useAuth };
