import { useEffect, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
  KEY_CATEGORY,
  KEY_LOCATION,
  KEY_PAGE,
  KEY_SEARCH,
  KEY_SORTBY,
  KEY_SUBCATEGORY,
} from "../../constants/queryStringConstants";
import { fetchCategories } from "../../store/actions/categories/categoriesActions";
import { fetchLocations } from "../../store/actions/locations/locationsActions";
import {
  selectOffers,
  selectTotalOffers,
} from "../../store/selectors/offersSelectors";
import useFilters from "./useFilters";
import useQueryString from "./useQueryString";
import { setQueryString } from "../../store/actions/queryString/queryStringActions";
import {
  convertQueryStringForBackend,
  makeHeaderStringHelper,
  makeQueryStringHelper,
} from "../../util/helpers/queryHelpers";
import useSorting from "./useSorting";
import useSearch from "./useSearch";
import {
  setHeaderString,
  setSearchString,
} from "../../store/actions/filters/filtersActions";
import usePaging from "./usePaging";
import { useHistory } from "react-router-dom";

const useOffers = () => {
  const dispatch = useDispatch();
  const filters = useFilters();
  const queryStringHook = useQueryString();
  const offers = useSelector(selectOffers);
  const totalOffers = useSelector(selectTotalOffers);
  const history = useHistory();

  // Always fetch categories and locations,
  // becouse count of total offers change over time
  useEffect(() => {
    dispatch(fetchCategories());
    dispatch(fetchLocations());
    return () => clear();
  }, []);

  useEffect(() => {
    console.log('location: ', history.location)
    if (history.location.state?.logo) {
      console.log('logo');
      clear();
    }
  }, [history.location])

  // On every change of query string, new header string should be created
  // Header string is shown on Home page above offers
  useEffect(() => {
    const headerStringLocal = makeHeaderStringHelper(filters);
    dispatch(setHeaderString(headerStringLocal));
  }, [queryStringHook.queryString]);

  // Initially set category, location and subcategory based on query string
  useEffect(() => {
    if (queryStringHook.isInitiallyLoaded) {
      const queryObject = queryStringHook.queryObject;
      if (KEY_CATEGORY in queryObject) {
        const category = filters.category.findCategory(
          queryObject[KEY_CATEGORY]
        );
        filters.category.setSelectedCategory(category);
        if (KEY_SUBCATEGORY in queryObject) {
          const subcategory = filters.category
            .getSubcategories(category?.name)
            .find(
              (subcategory) => subcategory.name === queryObject[KEY_SUBCATEGORY]
            );
          filters.subcategory.setSelectedSubcategory(subcategory);
        }
      }
      if (KEY_LOCATION in queryObject) {
        filters.locations.setSelectedLocationsFromArray(
          queryObject[KEY_LOCATION]
        );
      }
      if (KEY_SORTBY in queryObject) {
        sorting.changeSortingFromName(queryObject[KEY_SORTBY]);
      }
      if (KEY_PAGE in queryObject) {
        if (queryObject[KEY_PAGE] !== 1)
          paging.changePage(queryObject[KEY_PAGE]);
      }
      dispatch(setSearchString(queryObject[KEY_SEARCH]));
    }
  }, [queryStringHook.isInitiallyLoaded]);

  const allOffersToShow = useMemo(() => {
    return offers;
  }, [offers]);

  const apply = () => {
    filters.apply();
    const newQueryString = makeQueryStringHelper(
      filters,
      paging,
      search,
      sorting
    );
    dispatch(setQueryString(convertQueryStringForBackend(newQueryString)));
  };

  // Those hooks are below becouse function apply cannot be put on props before initialization
  const sorting = useSorting(apply);
  const paging = usePaging(apply);
  const search = useSearch(apply);

  // On every change of search string, offers should be immediately searched
  useEffect(() => {
    if (queryStringHook.isInitiallyLoaded) {
      search.searchOffers(search.searchString);
    }
  }, [search.searchString]);

  const clear = () => {
    filters.clear();
    sorting.clear();
    paging.changePage(1);
  };

  return {
    filters,
    sorting,
    paging,
    queryStringHook,
    allOffersToShow,
    totalOffers,
    apply,
    clear,
  };
};

export default useOffers;
