
  import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import MkdSDK from "Utils/MkdSDK";
import { getNonNullValue } from "Utils/utils";
import { PaginationBar } from "Components/PaginationBar";
import { AuthContext, tokenExpireError } from "Context/Auth";
import { GlobalContext } from "Context/Global";
import { MkdListTable, TableActions } from "Components/MkdListTable";
// import { MkdInput } from "Components/MkdInput";
import { BiFilterAlt, BiSearch } from "react-icons/bi";
import { AiOutlineClose, AiOutlinePlus } from "react-icons/ai";
import { RiDeleteBin5Line } from "react-icons/ri";
import { AddButton } from "Components/AddButton";
import { ExportButton } from "Components/ExportButton";
import { LazyLoad } from "Components/LazyLoad";
import { MkdDebounceInput } from "Components/MkdDebounceInput";
import TreeSDK from "Utils/TreeSDK";

let sdk = new MkdSDK();
// const getSchemaStructure = (schema) => {
//   return;
// };
const getType = (type) => {
  switch (type) {
    case "varchar":
      return "text";
    case "text":
      return "textarea";
    case "mediumtext":
      return "textarea";
    case "longtext":
      return "textarea";
    case "tinyint":
      return "number";
    case "int":
      return "number";
    case "bigint":
      return "number";
    case "float":
      return "number";
    case "double":
      return "number";
    case "image":
      return "image";
    case "file":
      return "file";
    case "date":
      return "date";
    case "datetime":
      return "datetime";
    default:
      return "text";
  }
};

const MkdListTableV2 = ({
  columns = [],
  actions = {
    view: { show: true, multiple: true, action: null },
    edit: { show: true, multiple: true, action: null },
    delete: { show: true, multiple: true, action: null },
    select: { show: true, multiple: true, action: null },
    add: {
      show: true,
      multiple: true,
      action: null,
      showChildren: true,
      children: "Add New",
    },
    export: { show: true, multiple: true, action: null },
  },
  actionPostion = "ontable",
  actionId = "id",
  tableRole = "admin",
  table = "user",
  tableTitle = "",
  tableSchema = [],
  hasFilter = true,
  schemaFields = [],
  showPagination = true,
  defaultFilter = [],
  refreshRef = null,
}) => {
  const tdk = new TreeSDK();

  const { dispatch } = React.useContext(AuthContext);
  const { dispatch: globalDispatch } = React.useContext(GlobalContext);

  const [query, setQuery] = React.useState("");
  const [currentTableData, setCurrentTableData] = React.useState([]);
  const [pageSize, setPageSize] = React.useState(10);
  const [pageCount, setPageCount] = React.useState(0);
  const [dataTotal, setDataTotal] = React.useState(0);
  const [currentPage, setPage] = React.useState(0);
  const [canPreviousPage, setCanPreviousPage] = React.useState(false);
  const [canNextPage, setCanNextPage] = React.useState(false);
  const [showDeleteModal, setShowDeleteModal] = React.useState(false);
  const [deleteLoading, setDeleteLoading] = React.useState(false);
  const [openFilter, setOpenFilter] = React.useState(false);
  const [showFilterOptions, setShowFilterOptions] = React.useState(false);
  const [selectedOptions, setSelectedOptions] = React.useState([]);
  const [filterConditions, setFilterConditions] = React.useState([]);
  const [selectedItems, setSelectedItems] = React.useState([]);
  const [searchValue, setSearchValue] = React.useState("");
  const [optionValue, setOptionValue] = React.useState("eq");
  const [isLoading, setIsLoading] = React.useState(false);
  const [loading, setLoading] = React.useState(false);

  const schema = yup.object({});

  const {
    register,
    handleSubmit,
    setError,
    reset,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(schema),
  });

  function onSort(columnIndex) {
    console.log(columns[columnIndex]);
    if (columns[columnIndex].isSorted) {
      columns[columnIndex].isSortedDesc = !columns[columnIndex].isSortedDesc;
    } else {
      columns.map((i) => (i.isSorted = false));
      columns.map((i) => (i.isSortedDesc = false));
      columns[columnIndex].isSorted = true;
    }

    (async function () {
      await getData(0, pageSize);
    })();
  }

  function updatePageSize(limit) {
    (async function () {
      setPageSize(limit);
      await getData(0, limit);
    })();
  }

  function previousPage() {
    (async function () {
      await getData(currentPage - 1 > 0 ? currentPage - 1 : 0, pageSize);
    })();
  }

  function nextPage() {
    (async function () {
      await getData(
        currentPage + 1 <= pageCount ? currentPage + 1 : 0,
        pageSize
      );
    })();
  }

  const addFilterCondition = (option, selectedValue, inputValue) => {
    const input =
      selectedValue === "eq" && isNaN(inputValue)
        ? `${inputValue}`
        : inputValue;
    const condition = `${option},${selectedValue},${input}`.toLowerCase();
    setFilterConditions((prevConditions) => {
      const newConditions = prevConditions.filter(
        (condition) => !condition.includes(option)
      );
      return [...newConditions, condition];
    });
    setSearchValue(inputValue);
  };
  // options.size = payload.limit;
  // options.order = payload.sortId;
  // options.direction = payload.direction;
  // options.page = payload.page;
  // options.join = payload.join;
  async function getData(pageNum, limitNum, currentTableData) {
    console.log("filterConditions >>", filterConditions);
    try {
      setLoading(true);
      const result = await tdk.getPaginate(table, {
        size: limitNum,
        page: pageNum,
        ...{
          ...(filterConditions.length
            ? {
                filter: [
                  ...(defaultFilter.length && defaultFilter),
                  ...filterConditions,
                ],
              }
            : defaultFilter.length
            ? { filter: [...defaultFilter] }
            : null),
        },
      });
      // sdk.setTable(table);
      // const result = await sdk.callRestAPI(
      //   {
      //     payload: {
      //       ...currentTableData,
      //       ...{
      //         ...(filterConditions.length
      //           ? {
      //               filter: [
      //                 ...(defaultFilter.length && defaultFilter),
      //                 ...filterConditions,
      //               ],
      //             }
      //           : defaultFilter.length
      //           ? { filter: [...defaultFilter] }
      //           : null),
      //       },
      //     },
      //     page: pageNum,
      //     limit: limitNum,
      //   },
      //   "PAGINATE"
      // );
      if (result) {
        setLoading(false);
      }
      const { list, total, limit, num_pages, page } = result;

      setCurrentTableData(list);
      console.log("v2 component fetch result");
      console.log(result);
      console.log("list");
      console.log(list);
      setPageSize(limit);
      setPageCount(num_pages);
      setPage(page);
      setDataTotal(total);
      setCanPreviousPage(page > 1);
      setCanNextPage(page + 1 <= num_pages);
      setLoading(false);
    } catch (error) {
      setLoading(false);
      console.log("ERROR", error);
      tokenExpireError(dispatch, error.message);
    }
  }

  const deleteItem = async (id) => {
    async function deleteId(id) {
      try {
        setDeleteLoading(true);
        sdk.setTable(table);
        const result = await sdk.callRestAPI({ id }, "DELETE");
        if (!result?.error) {
          setCurrentTableData((list) =>
            list.filter((x) => Number(x.id) !== Number(id))
          );
          setDeleteLoading(false);
          setShowDeleteModal(false);
        }
      } catch (err) {
        setDeleteLoading(false);
        setShowDeleteModal(false);
        tokenExpireError(dispatch, err?.message);
        throw new Error(err);
      }
    }

    if (typeof id === "object") {
      id.forEach(async (idToDelete) => {
        await deleteId(idToDelete);
      });
    } else if (typeof id === "number") {
      await deleteId(id);
    }
  };

  const exportTable = async (id) => {
    try {
      sdk.setTable(table);
      const result = await sdk.exportCSV();
    } catch (err) {
      throw new Error(err);
    }
  };

  const resetForm = async () => {
    reset();
    await getData(0, pageSize);
  };

  const onSubmit = (_data) => {
    let filter = {};
    for (const field of schemaFields) {
      const [key] = field.split(":");
      filter[key] = getNonNullValue(_data[key]);
    }
    getData(1, pageSize, filter);
  };

  async function updateTableData(id, key, updatedData) {
    try {
      // setLoading(true);
      sdk.setTable(table);
      const result = await sdk.callRestAPI(
        {
          id,
          [key]: updatedData,
        },
        "PUT"
      );
      // if (result) {
      //   setLoading(false);
      // }

      console.log("update user data");
      console.log(result);
    } catch (error) {
      // setLoading(false);
      console.log("ERROR", error);
      tokenExpireError(dispatch, error.message);
    }
  }

  async function handleTableCellChange(id, newValue, index, newValueKey) {
    console.log(newValue);
    console.log(index);
    console.log(newValueKey);
    let runApiCall;
    newValue = isNaN(Number.parseInt(newValue))
      ? newValue
      : Number.parseInt(newValue);
    try {
      clearTimeout(runApiCall);
      runApiCall = setTimeout(async () => {
        await updateTableData(id, newValueKey, newValue);
      }, 200);
      setCurrentTableData((prevData) => {
        const updatedData = prevData.map((item, i) => {
          if (i === index) {
            return {
              ...item,
              [newValueKey]: newValue,
            };
          }
          return item;
        });
        return updatedData;
      });
    } catch (error) {
      console.error(error);
    }
  }

  React.useEffect(() => {
    if (actions?.select?.action) {
      actions.select.action();
    }
  }, [selectedItems.length]);

  React.useEffect(() => {
    const delay = 700;
    const timeoutId = setTimeout(async () => {
      await getData(1, pageSize);
    }, delay);

    return () => {
      clearTimeout(timeoutId);
    };
  }, [searchValue, filterConditions, optionValue]);

  return (
    <div className="px-8">
      {refreshRef && (
        <button
          ref={refreshRef}
          onClick={() => getData(1, pageSize)}
          className="hidden"
        ></button>
      )}
      <div
        className={`flex gap-3 ${
          tableTitle ? "flex-col" : "h-fit items-center"
        }`}
      >
        {hasFilter ? (
          <div className="flex w-auto items-center justify-between ">
            <form
              className="relative rounded bg-white"
              onSubmit={handleSubmit(onSubmit)}
            >
              <div className="flex items-center gap-4 text-gray-700">
                <div
                  className="flex cursor-pointer items-center justify-between gap-3 rounded-md border border-gray-200 px-3 py-1"
                  onClick={() => setOpenFilter(!openFilter)}
                >
                  <BiFilterAlt />
                  <span>Filters</span>
                  {selectedOptions.length > 0 && (
                    <span className="flex h-6 w-6 items-center justify-center rounded-full bg-gray-800 text-start  text-white">
                      {selectedOptions.length > 0
                        ? selectedOptions.length
                        : null}
                    </span>
                  )}
                </div>
                <div className=" flex cursor-pointer items-center justify-between gap-3 rounded-md border border-gray-200 px-2 py-1 focus-within:border-gray-400">
                  <BiSearch className="text-xl text-gray-200" />
                  <input
                    type="text"
                    placeholder="search..."
                    className="border-none p-0 placeholder:text-left  focus:outline-none"
                    style={{ boxShadow: "0 0 transparent" }}
                    onInput={(e) =>
                      addFilterCondition("name", "cs", e.target?.value)
                    }
                  />
                  <AiOutlineClose className="text-lg text-gray-200" />
                </div>
              </div>
              {openFilter && (
                <div className="top-fill filter-form-holder absolute left-0  z-20 mt-4 min-w-[70%] rounded-md border border-gray-200 bg-white p-5 shadow-xl">
                  {selectedOptions?.map((option, index) => (
                    <div
                      key={index}
                      className="mb-2 flex w-full items-center justify-between gap-3 text-gray-600"
                    >
                      <div className=" mb-3  w-1/3 rounded-md border border-gray-300 px-3 py-2 leading-tight text-gray-700 outline-none">
                        {option}
                      </div>
                      <select
                        className="w-[30%] appearance-none border-none outline-0"
                        onChange={(e) => {
                          setOptionValue(e.target.value);
                        }}
                      >
                        <option value="eq" selected>
                          equals
                        </option>
                        <option value="cs">contains</option>
                        <option value="sw">start with</option>
                        <option value="ew">ends with</option>
                        <option value="lt">lower than</option>
                        <option value="le">lower or equal</option>
                        <option value="ge">greater or equal</option>
                        <option value="gt">greater than</option>
                        <option value="bt">between</option>
                        <option value="in">in</option>
                        <option value="is">is null</option>
                      </select>

                      <MkdDebounceInput
                        type="text"
                        placeholder="Enter value..."
                        setValue={() => {}}
                        showIcon={false}
                        className=" !mb-3 w-1/3 !rounded-md !border !border-gray-700 !px-3 !py-2 !leading-tight !text-gray-700 !outline-none"
                        onReady={(value) =>
                          addFilterCondition(option, optionValue, value)
                        }
                      />
                      {/* <p className="text-xs italic text-red-500">
                       {errors.id?.message}
                     </p> */}

                      <RiDeleteBin5Line
                        className=" cursor-pointer text-2xl"
                        onClick={() => {
                          setSelectedOptions((prevOptions) =>
                            prevOptions.filter((op) => op !== option)
                          );
                          setFilterConditions((prevConditions) => {
                            return prevConditions.filter(
                              (condition) => !condition.includes(option)
                            );
                          });
                        }}
                      />
                    </div>
                  ))}

                  <div className="search-buttons relative flex items-center justify-between font-semibold">
                    <div
                      // type="submit"
                      className="mr-2 flex w-auto cursor-pointer items-center gap-2 rounded bg-gray-100 px-4 py-2.5 font-medium leading-tight text-gray-600 transition duration-150 ease-in-out "
                      onClick={() => {
                        setShowFilterOptions(!showFilterOptions);
                      }}
                    >
                      <AiOutlinePlus />
                      Add filter
                    </div>

                    {showFilterOptions && (
                      <div className="absolute top-11 z-10 bg-white px-5 py-3 text-gray-600">
                        <ul className="flex flex-col gap-2 text-gray-500">
                          {columns
                            .map((column) => {
                              if (
                                column.hasOwnProperty("isFilter") &&
                                column.isFilter
                              ) {
                                return (
                                  <li
                                    key={column.header}
                                    className={`${
                                      selectedOptions.includes(column.accessor)
                                        ? "cursor-not-allowed text-gray-400"
                                        : "cursor-pointer"
                                    }`}
                                    onClick={() => {
                                      if (
                                        !selectedOptions.includes(column.header)
                                      ) {
                                        setSelectedOptions((prev) => [
                                          ...prev,
                                          column.accessor,
                                        ]);
                                      }
                                      setShowFilterOptions(false);
                                    }}
                                  >
                                    {column.header}
                                  </li>
                                );
                              } else if (!column.hasOwnProperty("isFilter")) {
                                return (
                                  <li
                                    key={column.header}
                                    className={`${
                                      selectedOptions.includes(column.accessor)
                                        ? "cursor-not-allowed text-gray-400"
                                        : "cursor-pointer"
                                    }`}
                                    onClick={() => {
                                      if (
                                        !selectedOptions.includes(column.header)
                                      ) {
                                        setSelectedOptions((prev) => [
                                          ...prev,
                                          column.accessor,
                                        ]);
                                      }
                                      setShowFilterOptions(false);
                                    }}
                                  >
                                    {column.header}
                                  </li>
                                );
                              }
                            })
                            .filter(Boolean)}
                        </ul>
                      </div>
                    )}
                    {selectedOptions.length > 0 && (
                      <div
                        // type="reset"
                        onClick={() => {
                          setSelectedOptions([]);
                          setFilterConditions([]);
                        }}
                        className="inline-block cursor-pointer  rounded px-6  py-2.5 font-medium leading-tight text-gray-600  transition duration-150 ease-in-out"
                      >
                        Clear all filter
                      </div>
                    )}
                  </div>
                </div>
              )}
            </form>
            {/* <AddButton link={"/admin/add-wireframe"} /> */}
          </div>
        ) : null}

        <div className="flex h-fit w-full justify-between text-center">
          <h4 className="text-2xl font-medium capitalize">
            {tableTitle ? tableTitle : ""}
          </h4>
          <div className="flex h-full gap-2">
            {selectedItems?.length && actionPostion === "abovetable" ? (
              <LazyLoad>
                <TableActions actions={actions} selectedItems={selectedItems} />
              </LazyLoad>
            ) : null}

            {actions?.export?.show && (
              <ExportButton
                showText={false}
                onClick={exportTable}
                className="mx-1"
              />
            )}

            {actions?.add?.show && (
              <AddButton
                onClick={() => {
                  if (actions?.add?.action) {
                    actions?.add?.action();
                  }
                }}
                showChildren={actions?.add?.showChildren}
              >
                {actions?.add?.children}
              </AddButton>
            )}
          </div>
        </div>
      </div>
      <div className="overflow-x-auto  rounded bg-white p-5 px-0">
        <MkdListTable
          onSort={onSort}
          columns={columns}
          tableRole={tableRole}
          actionId={actionId}
          table={table}
          tableTitle={tableTitle}
          deleteItem={deleteItem}
          loading={loading}
          deleteLoading={deleteLoading}
          showDeleteModal={showDeleteModal}
          currentTableData={currentTableData}
          setShowDeleteModal={setShowDeleteModal}
          actions={actions}
          actionPostion={actionPostion}
          setSelectedItems={setSelectedItems}
          handleTableCellChange={handleTableCellChange}
        />
      </div>
      {showPagination && (
        <PaginationBar
          currentPage={currentPage}
          pageCount={pageCount}
          pageSize={pageSize}
          canPreviousPage={canPreviousPage}
          canNextPage={canNextPage}
          updatePageSize={updatePageSize}
          previousPage={previousPage}
          nextPage={nextPage}
        />
      )}
    </div>
  );
};

export default MkdListTableV2;
  