"use client";

import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";

import styles from "@/components/administrator/CategoriesData/categoriesdata.module.css";

import Pagination from "@/components/ui/Pagination/pagination";
import Loader from "@/components/web/Loader/loader";
import Table from "@/components/administrator/Table/table";
import NewCategory from "../NewCategory/new.category";

import { useSearch } from "@/hooks/useSearch";
import { useTerm } from "@/hooks/useTerm";

import { FiSearch } from "react-icons/fi";
import { IoCloseOutline } from "react-icons/io5";
import { useRouter, useSearchParams } from "next/navigation";
import { termServices } from "@/app/services/api/term.services";

/**
 * @type {React.FC <{
 *     initialData: any[];
 *     limit: number;
 *     sort?: object;
 * }>}
 * @returns
 */
const CategoriesData = (props) => {
  const searchref = useRef(null);
  const searchParams = useSearchParams();
  const router = useRouter();

  const [initial, setInitial] = useState(props.initialData);
  const [categories, setCategories] = useState(props.initialData.data);
  const [selected, setSelected] = useState([]);
  const [isLoading, setIsLoading] = useState({
    data: false,
    delete: false,
  });

  const sort = useMemo(() => {
    try {
      const SORT = Object.fromEntries(searchParams.entries())?.sort;
      setCurrentPage(1);
      return JSON.parse(SORT);
    } catch (error) {
      return props.sort;
    }
  }, [searchParams, props.sort]);

  const categoriesData = useMemo(() => {
    return categories?.map((category) => ({
      ...category,
      hierarchy: (() => {
        const cat = Array.from(category.parents);
        if (cat?.length > 0)
          return cat
            .reverse()
            .map((item) => item.name)
            .join(" > ");
        return null;
      })(),
    }));
  }, [categories]);

  const {
    isLoading: loadSearch,
    isSearch,
    handleInput,
    handleSubmit,
    setInitialData,
    setSearchFn,
    setSetDataFn,
    setFallbackFn,
    cancel,
  } = useSearch();
  const { deleteMultipleCategory } = useTerm();

  const getSortedData = useCallback(async ({ page, limit }, sort) => {
    const data = await termServices.getCategories({ page, limit }, sort);
    setCategories(data.data);
  }, []);

  const setData = useCallback((data) => {
    setCategories(data);
  }, []);

  const onDeletedItem = useCallback(async () => {
    setSelected([]);
    const data = await termServices.getCategories({ page: 1, limit: 50 }, sort);

    setCategories(data.data);
    setInitial(data);
    cancel();
  }, [sort, cancel]);

  const fallback = useCallback(async (keyword, limit = 100) => {
    const result = await termServices.getCategories(
      { page: 1, limit },
      { name: 1 },
      keyword
    );

    return result.data;
  }, []);

  useEffect(() => {
    setIsLoading((prev) => ({ ...prev, data: loadSearch }));
  }, [loadSearch]);

  return (
    <div className={styles.post_container}>
      <div className={styles.post_header}>
        <div className={styles.header_wrapper}>
          <h1>Category Management</h1>
          <div className={styles.post_action}>
            {selected.length > 0 && (
              <div className={styles.post_status}>
                <p>
                  Selected:{" "}
                  <span>
                    {selected.length} item{selected.length > 1 && "s"}
                  </span>{" "}
                </p>
                <p>
                  <span
                    className={styles.action}
                    style={
                      isLoading.delete
                        ? { opacity: 0.5, pointerEvents: "none" }
                        : {}
                    }
                    onClick={async () => {
                      setIsLoading((prev) => ({ ...prev, delete: true }));
                      deleteMultipleCategory(
                        selected.map((item) => item._id),
                        async () => onDeletedItem(),
                        () =>
                          setIsLoading((prev) => ({ ...prev, delete: false }))
                      );
                    }}>
                    {isLoading.delete ? (
                      `Preparing to delete ${selected.length} item`
                    ) : (
                      <>Delete item{selected.length > 1 && "s"}</>
                    )}
                  </span>{" "}
                </p>
              </div>
            )}
            <NewCategory
              className={styles.post_button}
              fontSize={13}
              getCategory={(result) => {
                setCategories((prev) => [result, ...prev]);
              }}>
              Add Category
            </NewCategory>
          </div>
        </div>
        <div className={styles.header_wrapper}>
          <form
            className={styles.search_container}
            onSubmit={handleSubmit}>
            <FiSearch />
            <input
              type="text"
              ref={searchref}
              placeholder="Search Categories"
              defaultValue={props.initialData?.keyword || ""}
              onInput={handleInput}
              onFocus={() => {
                if (!isSearch) setInitialData(categories);

                setSearchFn(fallback);
                setFallbackFn(async () => {
                  setIsLoading((prev) => ({ ...prev, data: true }));
                  const data = await fallback(null, props?.limit);
                  setIsLoading((prev) => ({ ...prev, data: false }));
                  setData(data);
                });
                setSetDataFn(setData);
              }}
            />
            {isSearch && (
              <IoCloseOutline
                onClick={() => {
                  searchref.current.value = "";
                  cancel();
                }}
                style={{ cursor: "pointer" }}
              />
            )}
          </form>
        </div>
      </div>
      {isLoading.data ? (
        <div className={styles.loader_container}>
          <div className={styles.loader}>
            <Loader
              color="#000"
              width={30}
            />
            <p>Getting data</p>
          </div>
        </div>
      ) : (
        <Table
          data={categoriesData}
          selected={selected}
          limit={props.limit}
          role={{
            name: "Name",
            slug: "Slug",
            hierarchy: "Hierarchy",
            description: "Description",
          }}
          sortRole={{
            canSorting: true,
            excludeSorting: ["hierarchy"],
            sortingFn: getSortedData,
          }}
          onClick={(data) => {
            router.push(`/dashboard/categories/${data._id}`);
          }}
          onSelected={(data) => {
            setSelected(data);
          }}
        />
      )}
      {!isSearch && (
        <div className={styles.pagination}>
          <Pagination
            totalPage={initial.totalPage}
            currentPage={(() => {
              const page = parseInt(
                Object.fromEntries(searchParams.entries())?.page
              );
              return page || initial.page;
            })()}
            getData={termServices.getCategories}
            getIsLoading={(status) =>
              setIsLoading((prev) => ({ ...prev, data: status }))
            }
            setData={(data) => setCategories(data.data)}
            limit={props.limit}
            sort={sort}
          />
        </div>
      )}
    </div>
  );
};

export default CategoriesData;
