import React from "react";
import { AuthContext, tokenExpireError } from "../authContext";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import { GlobalContext, showToast } from "../globalContext";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import { getNonNullValue, removeKeysWhenValueIsNull } from "../utils/utils";
import PaginationBar from "Components/PaginationBar";
import AddButton from "Components/AddButton";
import ExportButton from "Components/ExportButton";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ClipLoader } from "react-spinners";

import {
  retrieveAllClientAPI,
  getAllClientAPI,
  getAllClientsAPI,
  myClients,
  retrieveAllForClientForMember,
} from "Src/services/clientService";
import { getUserDetailsByIdAPI } from "Src/services/userService";
import { retrieveAllForClientForManager } from "Src/services/managerServices";
import Spinner from "Components/Spinner";

const columns = [
  {
    header: "Program",
    accessor: "program",
    isSorted: false,
    isSortedDesc: false,
    mappingExist: false,
    mappings: {},
  },
  {
    header: "Position",
    accessor: "position",
    isSorted: false,
    isSortedDesc: false,
    mappingExist: false,
    mappings: {},
  },
  {
    header: "Name",
    accessor: "name",
    isSorted: false,
    isSortedDesc: false,
    mappingExist: false,
    mappings: {},
  },
  {
    header: "Email",
    accessor: "email",
    isSorted: false,
    isSortedDesc: false,
    mappingExist: false,
    mappings: {},
  },
  {
    header: "Phone",
    accessor: "phone",
    isSorted: false,
    isSortedDesc: false,
    mappingExist: false,
    mappings: {},
  },
];

const ListClientPage = () => {
  const { dispatch, state: authState } = React.useContext(AuthContext);
  const { dispatch: globalDispatch } = React.useContext(GlobalContext);

  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 [loading, setLoading] = React.useState(false);
  const [isLoading, setIsLoading] = React.useState(false);
  const [loader2, setLoader2] = React.useState(false);
  const [clients, setClients] = React.useState([]);

  // Check if pageSize exists in local storage
  const pageSizeFromLocalStorage = localStorage.getItem("clientPageSize");

  // Use a state variable to manage the pageSize
  const [pageSize, setPageSize] = React.useState(
    pageSizeFromLocalStorage ? Number(pageSizeFromLocalStorage) : 10 // Default pageSize
  );

  const navigate = useNavigate();

  const schema = yup.object({
    program: yup.string(),
    position: yup.string(),
    name: yup.string(),
    email: yup.string(),
    phone: yup.string(),
  });

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

  function onSort(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(1, pageSize);
    })();
  }

  function updatePageSize(limit) {
    (async function () {
      setLoader2(true);
      setPageSize(limit);
      await getData(1, limit);
      setLoader2(false);
      document.getElementById("mainContainer").scrollTo({
        top: 0,
        behavior: "smooth",
      });
    })();
    localStorage.setItem("clientPageSize", limit);
  }

  function previousPage() {
    (async function () {
      setLoader2(true);
      await getData(
        currentPage - 1,
        pageSizeFromLocalStorage ? Number(pageSizeFromLocalStorage) : pageSize
      );
      setLoader2(false);
      document.getElementById("mainContainer").scrollTo({
        top: 0,
        behavior: "smooth",
      });
    })();
  }

  function nextPage() {
    (async function () {
      setLoader2(true);
      await getData(
        currentPage + 1,
        pageSizeFromLocalStorage ? Number(pageSizeFromLocalStorage) : pageSize
      );
      setLoader2(false);
      document.getElementById("mainContainer").scrollTo({
        top: 0,
        behavior: "smooth",
      });
    })();
  }

  async function getData(pageNum, limitNum, filter) {
    currentTableData.length <= 0 ? setIsLoading(true) : setLoader2(true);
    try {
      const result = await retrieveAllForClientForMember(
        pageNum,
        limitNum,
        removeKeysWhenValueIsNull({
          ...filter,
        })
      );

      const { total, limit, num_pages, page, list } = result;

      // sort list by name alphabetically
      list.sort((a, b) => {
        if (a.client_program < b.client_program) {
          return -1;
        }
        return 1;
      });

      setCurrentTableData(list);
      setClients(result.list);
      // setPageSize(limit);
      setPageCount(num_pages);
      setPage(page);
      setDataTotal(total);
      setCanPreviousPage(page > 1);
      setCanNextPage(page + 1 <= num_pages);

      currentTableData.length <= 0 ? setIsLoading(false) : setLoader2(false);
    } catch (error) {
      currentTableData.length <= 0 ? setIsLoading(false) : setLoader2(false);
      tokenExpireError(dispatch, error.message);
    }
  }

  const callDataAgain = async (page) => {
    (async function () {
      setLoader2(true);
      await getData(
        page,
        pageSizeFromLocalStorage ? Number(pageSizeFromLocalStorage) : pageSize
      );
      setLoader2(false);
      document.getElementById("mainContainer").scrollTo({
        top: 0,
        behavior: "smooth",
      });
    })();
  };

  const resetForm = async () => {
    reset();
    localStorage.setItem("clientPageSize", 10);
    setPageSize(10);
    await getData(1, pageSize);
  };

  // const getAllClient = async () => {
  //   try {
  //     const result = await getAllClientAPI();
  //     if (!result.error) {
  //       setClients(result.list);
  //     } else {
  //       showToast(dispatch, 'Error exporting to CSV', 5000, 'error');
  //     }
  //   } catch (error) {
  //     tokenExpireError(dispatch, error.message);
  //   }
  // };

  const handleCopyAllEmails = (e) => {
    e.preventDefault();
    let emails = "";
    clients.forEach((client) => {
      emails += client.email + "; ";
    });
    navigator.clipboard.writeText(emails);
    showToast(globalDispatch, "Emails copied to clipboard", 5000);
  };

  const handleExportCSVFromTable = () => {
    const headers = [];

    for (let key in clients[0]) {
      let headerLabel = key;
      if (key === "has_auth") {
        headerLabel = "Enabled Login";
      } else if (key === "members") {
        headerLabel = "Members";
      }
      if (
        key !== "id" &&
        key !== "user_id" &&
        key !== "create_at" &&
        key !== "update_at" &&
        key !== "member_two_user_id" &&
        key !== "member_ids"
      ) {
        headers.push(
          headerLabel.charAt(0).toUpperCase() + headerLabel.slice(1)
        );
      }
    }

    // push the headers to csv at the first row
    const csv = [headers.join(",")];

    // push the data to csv
    for (let i = 0; i < clients.length; i++) {
      const row = [];

      for (const key in clients[i]) {
        let value = clients[i][key];
        if (key === "has_auth") {
          value = value === 1 ? "true" : "false";
        } else if (key === "members") {
          value = value.map((member) => member.name).join(", ");
        }
        if (
          key !== "id" &&
          key !== "user_id" &&
          key !== "create_at" &&
          key !== "update_at" &&
          key !== "member_two_user_id" &&
          key !== "member_ids"
        ) {
          row.push(value);
        }
      }
      csv.push(row.join(","));
    }

    // Download CSV file
    let currentDateTime = new Date();
    downloadCSV(csv.join("\n"), "Client_list_" + currentDateTime + ".csv");
  };
  const downloadCSV = (csv, filename) => {
    let csvFile;
    let downloadLink;
    // CSV file
    csvFile = new Blob([csv], { type: "text/csv" });
    // Download link
    downloadLink = document.createElement("a");
    // File name
    downloadLink.download = filename;
    // Create a link to the file
    downloadLink.href = window.URL.createObjectURL(csvFile);
    // Hide download link
    downloadLink.style.display = "none";
    // Add the link to DOM
    document.body.appendChild(downloadLink);
    // Click download link
    downloadLink.click();
  };

  const onSubmit = (_data) => {
    let program = getNonNullValue(_data.program);
    let position = getNonNullValue(_data.position);
    let name = getNonNullValue(_data.name);
    let email = getNonNullValue(_data.email);
    let phone = getNonNullValue(_data.phone);
    let filter = {
      program: program,
      position: position,
      name: name,
      email: email,
      phone: phone,
    };
    getData(1, pageSize, removeKeysWhenValueIsNull(filter));
  };

  React.useEffect(() => {
    globalDispatch({
      type: "SETPATH",
      payload: {
        path: "clients",
      },
    });

    // (async function () {
    //   await getAllClient();
    //   await getData(1, pageSize);
    // })();

    if (!pageSizeFromLocalStorage) {
      // call the API to get the data
      (async function () {
        setLoading(true);
        await getData(1, pageSize);
        // await getAllClient();
      })();
    } else {
      // call the API to get the data
      (async function () {
        setLoading(true);
        await getData(1, pageSizeFromLocalStorage);
        // await getAllClient();
      })();
    }
  }, []);

  const SubscriptionType = localStorage.getItem("UserSubscription");

  React.useEffect(() => {
    const userId = localStorage.getItem("user");

    if (userId) {
      (async function () {
        try {
          const result = await getUserDetailsByIdAPI(userId);

          if (!result?.error) {
            localStorage.setItem(
              "UserSubscription",
              result?.model?.subscription
            );
          }
        } catch (error) {}
      })();
    }
  }, []);

  return (
    <div
      className="p-4 h-full max-w-screen md:p-4 lg:p-6 xl:p-8"
      id="mainContainer"
    >
      <div className="rounded border shadow-default border-strokedark bg-boxdark dark:border-strokedark dark:bg-boxdark">
        <div className="flex justify-between items-center px-4 border-b border-strokedark md:px-6 2xl:px-9">
          <h4 className="my-3 text-2xl font-semibold text-white dark:text-white">
            Clients
          </h4>
          <div className="flex gap-2 items-center">
            <AddButton link={`/${authState.role}/add-client`} />
            {clients && clients.length > 0 && (
              <>
                <button
                  onClick={handleCopyAllEmails}
                  className="inline-flex h-[32px] w-[32px] items-center justify-center rounded bg-primary text-white hover:bg-opacity-90"
                >
                  <FontAwesomeIcon
                    icon="fa-solid fa-clipboard"
                    className="w-4 h-4"
                  />
                </button>
                <ExportButton onClick={handleExportCSVFromTable} />
              </>
            )}
          </div>
        </div>
        {/* Header Section */}
        <div className="px-4 py-4 mb-4 border-b border-strokedark sm:px-6 2xl:px-9 dark:border-strokedark">
          <div className="">
            <form onSubmit={handleSubmit(onSubmit)} className="">
              <div className="flex gap-3 items-center">
                {/* Program Input */}
                <div className="flex flex-col">
                  <label className="mb-1.5 text-sm font-medium text-white">
                    Program
                  </label>
                  <input
                    type="text"
                    placeholder="program"
                    {...register("program")}
                    className="h-[36px] w-64 rounded border-[1.5px] border-form-strokedark bg-form-input px-3 py-2 text-sm outline-none transition placeholder:font-normal placeholder:text-bodydark focus:border-primary active:border-primary disabled:cursor-default disabled:bg-whiter dark:border-form-strokedark dark:bg-form-input dark:focus:border-primary"
                  />
                </div>

                {/* Position Input */}
                <div className="flex flex-col">
                  <label className="mb-1.5 text-sm font-medium text-white">
                    Position
                  </label>
                  <input
                    type="text"
                    placeholder="position"
                    {...register("position")}
                    className="h-[36px] w-64 rounded border-[1.5px] border-form-strokedark bg-form-input px-3 py-2 text-sm outline-none transition placeholder:font-normal placeholder:text-bodydark focus:border-primary active:border-primary disabled:cursor-default disabled:bg-whiter dark:border-form-strokedark dark:bg-form-input dark:focus:border-primary"
                  />
                </div>

                {/* Name Input */}
                <div className="flex flex-col">
                  <label className="mb-1.5 text-sm font-medium text-white">
                    Name
                  </label>
                  <input
                    type="text"
                    placeholder="name"
                    {...register("name")}
                    className="h-[36px] w-64 rounded border-[1.5px] border-form-strokedark bg-form-input px-3 py-2 text-sm outline-none transition placeholder:font-normal placeholder:text-bodydark focus:border-primary active:border-primary disabled:cursor-default disabled:bg-whiter dark:border-form-strokedark dark:bg-form-input dark:focus:border-primary"
                  />
                </div>

                {/* Email Input */}
                <div className="flex flex-col">
                  <label className="mb-1.5 text-sm font-medium text-white">
                    Email
                  </label>
                  <input
                    type="text"
                    placeholder="email"
                    {...register("email")}
                    className="h-[36px] w-64 rounded border-[1.5px] border-form-strokedark bg-form-input px-3 py-2 text-sm outline-none transition placeholder:font-normal placeholder:text-bodydark focus:border-primary active:border-primary disabled:cursor-default disabled:bg-whiter dark:border-form-strokedark dark:bg-form-input dark:focus:border-primary"
                  />
                </div>
              </div>

              {/* Action Buttons */}
              <div className="flex gap-2 items-center mt-3">
                <button
                  type="submit"
                  className="inline-flex h-[36px] items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-white hover:bg-opacity-90"
                >
                  Search
                </button>
                <button
                  onClick={resetForm}
                  type="button"
                  className="inline-flex h-[36px] items-center justify-center rounded-md border border-strokedark bg-danger px-4 py-2 text-sm font-medium text-white hover:bg-opacity-90"
                >
                  Reset
                </button>
              </div>
            </form>
          </div>
        </div>

        <div>
          {/* Table Content */}
          <div className="custom-overflow min-h-[140px] overflow-x-auto">
            <table className="w-full table-auto">
              <thead className="bg-meta-4">
                <tr>
                  {columns.map((column, i) => (
                    <th
                      key={i}
                      onClick={() => onSort(i)}
                      className={`cursor-pointer px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-white ${
                        i === 0 ? "2xl:pl-9" : ""
                      }`}
                    >
                      {column.header}
                      <span>
                        {column.isSorted
                          ? column.isSortedDesc
                            ? " ▼"
                            : " ▲"
                          : ""}
                      </span>
                    </th>
                  ))}
                </tr>
              </thead>

              {!isLoading && currentTableData.length > 0 ? (
                <tbody className="text-white cursor-pointer">
                  {currentTableData.map((row, i) => (
                    <tr
                      key={i}
                      className="border-b border-strokedark hover:bg-primary/5"
                      onClick={() => {
                        navigate(`/${authState.role}/view-client/${row.id}`, {
                          state: row,
                        });
                      }}
                    >
                      {columns.map((cell, index) => {
                        if (cell.mappingExist) {
                          return (
                            <td
                              key={index}
                              className="px-6 py-4 whitespace-nowrap"
                            >
                              {cell.mappings[row[cell.accessor]]}
                            </td>
                          );
                        }
                        return (
                          <td
                            key={index}
                            className="px-6 py-4 whitespace-nowrap 2xl:pl-9"
                          >
                            {row[cell.accessor]}
                          </td>
                        );
                      })}
                    </tr>
                  ))}
                </tbody>
              ) : isLoading && currentTableData.length === 0 ? (
                <tbody>
                  <tr>
                    <td colSpan={columns.length} className="text-center">
                      <span className="trans relative top-[30px] m-4 animate-pulse whitespace-nowrap p-4 pb-8 text-xl font-semibold text-white ease-out">
                        <ClipLoader color="#fff" size={20} className="mr-3" />{" "}
                        Loading Clients...
                      </span>
                    </td>
                  </tr>
                </tbody>
              ) : !isLoading && currentTableData.length === 0 ? (
                <tbody>
                  <tr>
                    <td colSpan={columns.length} className="text-center">
                      <span className="relative top-[10px] m-4 p-4 font-semibold text-white">
                        No data found
                      </span>
                    </td>
                  </tr>
                </tbody>
              ) : null}
            </table>
          </div>

          {/* Pagination */}
          {currentTableData.length > 0 && !isLoading && (
            <div className="px-4 py-10 w-full md:px-6 2xl:px-9">
              <PaginationBar
                currentPage={currentPage}
                pageCount={pageCount}
                pageSize={pageSize}
                callDataAgain={callDataAgain}
                canPreviousPage={canPreviousPage}
                canNextPage={canNextPage}
                updatePageSize={updatePageSize}
                previousPage={previousPage}
                nextPage={nextPage}
                dataTotal={dataTotal}
                setCurrentPage={setPage}
              />
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default ListClientPage;
