import { cloneDeep, isEqual, unset } from "lodash";
import { ReactNode, createContext, useEffect, useMemo, useState } from "react";
// form
import { useLocation } from "react-router";
import { Dictionary } from "@types";
import useNavigateCustom from "hooks/useNavigateCustom";

// ----------------------------------------------------------------------

const _condition: Dictionary = {};

const initialState = {
  initialized: false,
  condition: _condition,
  get: (key: string): string => "",
  initializeCondition: () => {},
  addCondition: (condition: Dictionary) => {
    console.log("not init SearchConditionContext");
  },
  clearCondition: () => {},
};

export const SearchConditionContext = createContext(initialState);
type Props = {
  children: ReactNode;
};

export function SearchConditionContextProvider({ children }: Props) {
  const [condition, _setCondition] = useState<Dictionary>({});
  const [initialized, setInitialized] = useState(false);

  const { pathname, search } = useLocation();
  const { navigateWhenChanged } = useNavigateCustom();

  const setCondition = (after: Dictionary, message?: any) => {
    if (message) {
      console.log("Contidion Change", { after, message });
    }
    _setCondition(after);
  };

  const initializeCondition = () => {
    const after: Dictionary = {};
    const urlParam = new URLSearchParams(search);
    for (const [key, value] of urlParam.entries()) {
      after[key] = value;
    }

    if (!isEqual(after, condition)) {
      setCondition(after, "initializeCondition");
    }
    setInitialized(true);
  };

  const get = (key: string) => {
    return condition[key] ?? "";
  };

  const getCondition = useMemo(() => {
    return cloneDeep(condition);
  }, [condition]);

  const addCondition = (additional: Dictionary) => {
    if (!initialized) return;
    const before = cloneDeep(condition);
    const after = cloneDeep(condition);

    Object.keys(additional).forEach((key) => {
      unset(after, key);
      if (additional[key] !== "") {
        after[key] = additional[key];
      }
    });

    // console.log("compare condition", {
    //   before,
    //   after,
    // });
    if (!isEqual(before, after)) {
      // console.log("add condition", {
      //   before,
      //   after,
      // });
      setCondition(after, "addCondition");
    }
  };

  const searchParams = useMemo(() => {
    const params = new URLSearchParams();
    if (!initialized) return params;

    Object.keys(condition).forEach((key) => {
      params.append(key, condition[key]);
    });
    params.sort();
    return params;
  }, [condition]);

  const applyToURL = () => {
    if (!initialized) return;

    navigateWhenChanged(pathname, condition, "applyToURL");
  };

  const clearCondition = () => {
    setCondition({}, "clearCondition");
    setInitialized(false);
  };

  useEffect(() => {
    if (initialized) {
      // console.log("call applyToURL", { condition, initialized });
      applyToURL();
    }
  }, [condition, initialized]);

  useEffect(() => {
    initializeCondition();
  }, [pathname, search]);

  return (
    <SearchConditionContext.Provider
      value={{
        condition: getCondition,
        initialized,
        get,
        initializeCondition,
        addCondition,
        clearCondition,
      }}
    >
      {children}
    </SearchConditionContext.Provider>
  );
}
