import Failure from "core/failure";
import debounce from "lodash.debounce";
import { UpdateUserArtifacts } from "user/domain/userModel";
import { User } from "../domain/userEntity";
import { UserStore } from "../domain/userStore";

type UpdateUserStore = Pick<
  UserStore,
  "user" | "updateUser" | "setUser"
>;

const deboucedTask = debounce((task) => Promise.resolve(task()), 500);

type K = keyof User | undefined;
type Payload<T extends K = undefined> =  T extends undefined ? undefined : User[NonNullable<T>];

const updateUserUseCase = <T extends K = undefined>(
  store: UpdateUserStore,
  updateBy: (user: User, ...payload: T extends undefined ? [] : [Payload<T>]) => UpdateUserArtifacts,
  ...payload: T extends undefined ? []: [Payload<T>]
) => {
  const updateArtifacts = store.user
    ? updateBy(store.user, ...payload)
    : store.user;

  if (updateArtifacts) {
    store.setUser(updateArtifacts.user);

    return deboucedTask(() => store.updateUser(updateArtifacts.diff));
  }
  return Promise.reject(new Failure({message: 'mutation unknown or user object is not exists', key: "failures.user.empty"}));
};

export { updateUserUseCase };

export type { UpdateUserStore };
