import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import Column from "../../../components/common/columns";
import { Paginated } from "../../../services/Paginated";
import DomainsTable from "./components/domainsTable";
import domainsService, { GetDomain } from "./serrvices/domainsService";
import Button, { ButtonType } from "../../../components/common/Button";
import Loading from "../../../components/common/Loading";
import Permission from "../../../components/common/Permission";

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

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

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

  useEffect(() => {
    const loadInitial = async () => {
      await changePage(initialPagedData.page, initialPagedData.pageSize);
    };

    void loadInitial();
  }, [changePage]);

  const onSort = async (nextSortColumn: Column<GetDomain>) => {
    const { page, pageSize } = pagedData;
    const pagedDataResult = await domainsService.getDomains(
      page,
      pageSize,
      nextSortColumn.key,
      nextSortColumn.order === "asc",
      filters,
    );
    if (pagedDataResult) {
      setLoaded(true);
      setPagedData(pagedDataResult);
      setSortColumn(nextSortColumn);
    } else {
      setLoaded(false);
    }
  };

  const onSearch = async (name: string, value: string) => {
    const { page, pageSize } = pagedData;
    const nextFilters = new Map(filters);
    nextFilters.set(name, value);

    const pagedDataResult = await domainsService.getDomains(
      page,
      pageSize,
      sortColumn.key,
      sortColumn.order === "asc",
      nextFilters,
    );
    if (pagedDataResult) {
      setLoaded(true);
      setFilters(nextFilters);
      setPagedData(pagedDataResult);
    } else {
      setLoaded(false);
    }
  };

  const onDelete = async (keyValue?: GetDomain) => {
    const response = await domainsService.deleteDomain(
      keyValue?.id,
      keyValue?.guid,
    );
    if (response) {
      await changePage(pagedData.page, pagedData.pageSize);
    }
  };

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

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

export default Domains;
