import { sleep } from "@/lib/utils";
import { PermissionEnum } from "@/types/permission";
import React, { useContext, useEffect, useMemo } from "react";
import { useCallback, useState } from "react";

export interface IAuthContext {
  isAuthenticated: boolean;
  setAuthenticated: (value: boolean) => void;
  logout: () => Promise<void>;
  login: (username: string) => void;
  username: string;
  token: string;
  name: string;
  acs: number[];
  hasPermission: (permission: PermissionEnum) => boolean;
  role: {
    roleName: string;
    priority: number;
  };
}

const AuthContext = React.createContext<IAuthContext | null>(null);

const key = "computersmanagement.auth.user";

function getStoredUser() {
  return localStorage.getItem(key);
}

function setStoredUser(user: string | null) {
  if (user) {
    localStorage.setItem(key, user);
  } else {
    localStorage.removeItem(key);
  }
}

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<string>(getStoredUser() || "");
  const [isAuthenticated, setIsAuthenticated] = useState<boolean>(!!user);
  const token = localStorage.getItem("token") || "";
  const name = localStorage.getItem("name") || "";
  const acsString = localStorage.getItem("acs");
  const acs = useMemo(() => (acsString ? acsString.split(",").map(Number) : []), [acsString]);
  const roleName = localStorage.getItem("role") || "";
  const priority = localStorage.getItem("priority") || "-1";

  const setAuthenticated = useCallback((value: boolean) => {
    setIsAuthenticated(value);
  }, []);

  const login = useCallback((username: string) => {
    setStoredUser(username);
    setUser(username);
  }, []);

  const hasPermission = useCallback(
    (permission: PermissionEnum) => {
      return acs.some((a) => a === permission);
    },
    [acs]
  );

  const logout = useCallback(async () => {
    await sleep(250);
    setAuthenticated(false);
    setStoredUser("");
    setUser("");
    localStorage.removeItem("token");
    localStorage.removeItem("name");
    localStorage.removeItem("acs");
    localStorage.removeItem("role");
    localStorage.removeItem("priority");
  }, [setAuthenticated]);

  useEffect(() => {
    setUser(getStoredUser() || "");
  }, []);

  return (
    <AuthContext.Provider
      value={{
        isAuthenticated,
        setAuthenticated,
        login,
        logout,
        username: user,
        token,
        name,
        acs,
        role: { roleName, priority: Number(priority) },
        hasPermission
      }}>
      {children}
    </AuthContext.Provider>
  );
}

// eslint-disable-next-line react-refresh/only-export-components
export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}
