import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useParams } from "react-router-dom";
import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated";
import Button, { ButtonType } from "../../../components/common/Button";
import siteService, { ReadSite } from "./services/sitessService";
import SitesTable from "./components/SitesTable";
import Loading from "../../../components/common/Loading";
import Permission from "../../../components/common/Permission";

const initialPagedData: Paginated<ReadSite> = {
  page: 1,
  pageSize: 10,
  count: 0,
  totalPages: 1,
  data: [],
};

const Sites: React.FC = () => {
  const { t } = useTranslation(Namespaces.Common);
  const { organisationId } = useParams<{ organisationId: string }>();

  const [loaded, setLoaded] = useState(false);
  const [pagedData, setPagedData] =
    useState<Paginated<ReadSite>>(initialPagedData);
  const [sortColumn, setSortColumn] = useState<Column<ReadSite>>({
    key: "name",
    label: t("Name"),
    order: "asc",
  });
  const [filters, setFilters] = useState<Map<string, string>>(
    () => new Map<string, string>(),
  );

  const updateFiltersWithOrganisationId = useCallback(
    (nextFilters: Map<string, string>) => {
      const updatedFilters = new Map(nextFilters);
      if (organisationId) {
        updatedFilters.set("organisationId", organisationId);
      }
      return updatedFilters;
    },
    [organisationId],
  );

  const changePage = useCallback(
    async (page: number, pageSize: number) => {
      const nextFilters = updateFiltersWithOrganisationId(filters);
      const pagedDataResult = await siteService.getSites(
        page,
        pageSize,
        sortColumn.key,
        sortColumn.order === "asc",
        nextFilters,
      );
      if (pagedDataResult) {
        setLoaded(true);
        setFilters(nextFilters);
        setPagedData(pagedDataResult);
      } else {
        setLoaded(false);
      }
    },
    [
      filters,
      sortColumn.key,
      sortColumn.order,
      updateFiltersWithOrganisationId,
    ],
  );

  useEffect(() => {
    const loadInitial = async () => {
      const nextFilters = updateFiltersWithOrganisationId(
        new Map<string, string>(),
      );
      const pagedDataResult = await siteService.getSites(
        initialPagedData.page,
        initialPagedData.pageSize,
        "name",
        true,
        nextFilters,
      );
      if (pagedDataResult) {
        setLoaded(true);
        setFilters(nextFilters);
        setPagedData(pagedDataResult);
      } else {
        setLoaded(false);
      }
    };

    void loadInitial();
  }, [updateFiltersWithOrganisationId]); // eslint-disable-line react-hooks/exhaustive-deps

  const onSort = useCallback(
    async (nextSortColumn: Column<ReadSite>) => {
      const { page, pageSize } = pagedData;
      const nextFilters = updateFiltersWithOrganisationId(filters);
      const pagedDataResult = await siteService.getSites(
        page,
        pageSize,
        nextSortColumn.key,
        nextSortColumn.order === "asc",
        nextFilters,
      );
      if (pagedDataResult) {
        setLoaded(true);
        setFilters(nextFilters);
        setPagedData(pagedDataResult);
        setSortColumn(nextSortColumn);
      } else {
        setLoaded(false);
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [filters, updateFiltersWithOrganisationId],
  );

  const onSearch = useCallback(
    async (name: string, value: string) => {
      const { page, pageSize } = pagedData;
      const nextFilters = new Map(filters);
      nextFilters.set(name, value);
      const updatedFilters = updateFiltersWithOrganisationId(nextFilters);
      const pagedDataResult = await siteService.getSites(
        page,
        pageSize,
        sortColumn.key,
        sortColumn.order === "asc",
        updatedFilters,
      );
      if (pagedDataResult) {
        setLoaded(true);
        setFilters(updatedFilters);
        setPagedData(pagedDataResult);
      } else {
        setLoaded(false);
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [
      filters,
      sortColumn.key,
      sortColumn.order,
      updateFiltersWithOrganisationId,
    ],
  );

  const onDelete = useCallback(
    async (item?: ReadSite) => {
      await siteService.deleteSite(item?.id, item?.guid);
      await changePage(pagedData.page, pagedData.pageSize);
    },
    [changePage], // eslint-disable-line react-hooks/exhaustive-deps
  );

  const translatedSortColumn = useMemo(
    () => ({ ...sortColumn, label: t("Name") }),
    [sortColumn, t],
  );

  return (
    <Loading loaded={loaded}>
      <Permission privilegeKey="AddSite">
        <div>
          <Button buttonType={ButtonType.primary} to="add">
            {t("Add")}
          </Button>
        </div>
      </Permission>
      <hr />
      <SitesTable
        data={pagedData}
        sortColumn={translatedSortColumn}
        onChangePage={changePage}
        onSort={onSort}
        onSearch={onSearch}
        onDelete={onDelete}
      />
    </Loading>
  );
};

export default Sites;
