import React, { useState, useContext, useMemo, ReactNode } from "react";
import { endpoints } from "../utils/api";
import { PermissionsDto } from "types/dtos";
import { useSWR, fetcher } from "units/swr";
import { blip } from "utils";

const permissionCodes = {
  VIEW_DASHBOARD: "VIEW_DASHBOARD",
  MANAGE_USERS: "MANAGE_USERS",
  MANAGE_SETTINGS: "MANAGE_SETTINGS",
  VIEW_MACHINES: "VIEW_MACHINES",
  MANAGE_MACHINES: "MANAGE_MACHINES",
  OPERATE_MACHINES: "OPERATE_MACHINES",
  GUEST_ACCESS: "GUEST_ACCESS",
  SYSTEM_ADMINISTRATION: "SYSTEM_ADMINISTRATION"
};

type UserPermissionsContextPayload = {
  permissions: string[];
  loading: boolean;
};

const initialState: UserPermissionsContextPayload = {
  permissions: [],
  loading: true
};

const getPermissionFlags = (permissions: string[]) => {
  const viewDashboard = permissions.includes(permissionCodes.VIEW_DASHBOARD) ?? false;
  const manageUsers = permissions.includes(permissionCodes.MANAGE_USERS) ?? false;
  const manageSettings = permissions.includes(permissionCodes.MANAGE_SETTINGS) ?? false;
  const viewMachines = permissions.includes(permissionCodes.VIEW_MACHINES) ?? false;
  const manageMachines = permissions.includes(permissionCodes.MANAGE_MACHINES) ?? false;
  const operateMachines = permissions.includes(permissionCodes.OPERATE_MACHINES) ?? false;
  const guestAccess = permissions.includes(permissionCodes.GUEST_ACCESS) ?? false;
  const sysAdmin = permissions.includes(permissionCodes.SYSTEM_ADMINISTRATION) ?? false;

  const flags = {
    viewDashboard,
    manageUsers,
    manageSettings,
    viewMachines,
    manageMachines,
    operateMachines,
    guestAccess,
    sysAdmin
  };

  const isGuest = guestAccess === true;
  const isUser = Object.values(flags).includes(true) && !flags.guestAccess;

  return {
    ...flags,
    isGuest,
    isUser
  };
};

const UserPermissionsContext = React.createContext<UserPermissionsContextPayload>(initialState);

const usePermissions = () => {
  const { permissions, loading } = useContext(UserPermissionsContext);
  const flags = useMemo(() => getPermissionFlags(permissions), [permissions]);
  return { loading, ...flags };
};

type Props = {
  children: ReactNode;
};

const UserPermissionsProvider: React.FC<Props> = ({ children }) => {
  const [state, setState] = useState<UserPermissionsContextPayload>(initialState);

  const url = useMemo(() => (state.permissions?.length ? null : endpoints.security.permissions), [state.permissions]);
  useSWR<PermissionsDto, Error>(url, fetcher, {
    revalidateOnFocus: false,
    onError: err => blip.error(err.message),
    onSuccess: data => setState({ ...data, loading: false })
  });

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

export { UserPermissionsProvider, usePermissions };
export default UserPermissionsProvider;
