<script lang="ts">
  import { DirectorySyncProviders, Directory } from "../types";
  import LoadingContainer from "../../shared/LoadingContainer/index.svelte";
  import type { DirectoryListProps, DirectoryType } from "../types";
  import defaultClasses from "./index.module.css";
  import {
    BadgeProps,
    PageToken,
    PaginatePayload,
    TableProps,
  } from "../../shared/types";
  import { sendHTTPRequest } from "../../shared/http";
  import Paginate from "../../shared/Paginate/index.svelte";
  import PaginatedTable from "../../shared/Table/paginated.svelte";
  import NonPaginatedTable from "../../shared/Table/non-paginated.svelte";
  const DEFAULT_VALUES = {
    directoryListData: [] as Directory[],
  };

  export let urls: DirectoryListProps["urls"];
  export let paginate: DirectoryListProps["paginate"] = undefined;
  export let hideViewAction: DirectoryListProps["hideViewAction"] = undefined;
  export let handleActionClick: DirectoryListProps["handleActionClick"];
  export let cols: DirectoryListProps["cols"] = undefined;
  export let tenant: DirectoryListProps["tenant"] = undefined;
  export let product: DirectoryListProps["product"] = undefined;
  export let tableProps: DirectoryListProps["tableProps"] = undefined;
  export let errorCallback: DirectoryListProps["errorCallback"] = undefined;
  export let handleListFetchComplete: DirectoryListProps["handleListFetchComplete"] =
    undefined;

  function listFetchUrl(
    params: Partial<PaginatePayload> &
      Pick<DirectoryListProps, "tenant" | "product"> & {
        getUrl: string;
      }
  ) {
    let _url = params.getUrl;
    const [urlPath, qs] = _url.split("?");
    const urlParams = new URLSearchParams(qs);
    if (params.tenant) {
      urlParams.set("tenant", params.tenant);
    }
    if (params.product) {
      urlParams.set("product", params.product);
    }
    if (params.pageToken) {
      urlParams.set("pageToken", params.pageToken);
    }
    if (params?.offset !== undefined) {
      urlParams.set("pageOffset", `${params.offset}`);
      urlParams.set("pageLimit", `${params.limit}`);
    }
    if (urlParams.toString()) {
      return `${urlPath}?${urlParams}`;
    }
    return _url;
  }
  function updateTokenMap(offset: number, token: PageToken) {
    return {
      ...pageTokenMap,
      [offset]: token,
    };
  }
  async function getFieldsData(directoryListUrl: string) {
    // fetch request for obtaining directory lists data
    const response = await sendHTTPRequest<
      | {
          data: Directory[];
        }
      | {
          data: {
            data: Directory[];
          };
          pageToken: PageToken;
        }
    >(directoryListUrl);
    isDirectoryListLoading = false;
    if (response && typeof response === "object") {
      if ("error" in response && response.error) {
        showErrorComponent = true;
        errorMessage = response.error.message;
        typeof errorCallback === "function" &&
          errorCallback(response.error.message);
      } else if ("data" in response) {
        const isTokenizedPagination = "pageToken" in response;
        const _data = isTokenizedPagination
          ? response.data.data
          : response.data;
        if (Array.isArray(_data)) {
          const directoriesListData = _data.map((directory: Directory) => {
            return {
              ...directory,
              id: directory.id,
              name: directory.name,
              tenant: directory.tenant,
              product: directory.product,
              type: providers().find(({ value }) => value === directory.type)
                ?.text as DirectoryType,
              status: directory.deactivated ? "Inactive" : "Active",
            };
          });
          directoryListData = directoriesListData;
          typeof handleListFetchComplete === "function" &&
            handleListFetchComplete(directoriesListData);
        }
        if (isTokenizedPagination) {
          return response.pageToken;
        }
      }
    }
  }
  async function reFetch(payload: PaginatePayload) {
    const pageToken = await getFieldsData(
      listFetchUrl({
        getUrl: baseFetchUrl(),
        ...payload,
      })
    );
    if (pageToken) {
      pageTokenMap = updateTokenMap(payload.offset, pageToken);
    }
  }
  $: providers = () => {
    return Object.entries<string>(DirectorySyncProviders)?.map(
      ([value, text]) => ({
        value,
        text,
      })
    );
  };
  $: getUrl = () => {
    return urls.get;
  };
  $: isPaginated = () => {
    return paginate?.itemsPerPage !== undefined;
  };
  $: actions = () => {
    if (hideViewAction) {
      return [
        {
          icon: "PencilIcon",
          label: "Edit",
          handleClick: (directory: Directory) =>
            handleActionClick("edit", directory),
        },
      ];
    }
    return [
      {
        icon: "EyeIcon",
        label: "View",
        handleClick: (directory: Directory) =>
          handleActionClick("view", directory),
      },
      {
        icon: "PencilIcon",
        label: "Edit",
        handleClick: (directory: Directory) =>
          handleActionClick("edit", directory),
      },
    ];
  };
  $: colsToDisplay = () => {
    return (
      cols || ["name", "tenant", "product", "type", "status", "actions"]
    ).map((_col) => {
      if (_col === "status") {
        return {
          name: "status",
          badge: {
            position: "surround",
            variantSelector(rowData) {
              let _variant: BadgeProps["variant"];
              if (rowData.deactivated) {
                _variant = "warning";
              }
              if (!rowData.deactivated) {
                _variant = "success";
              }
              return _variant;
            },
          },
        };
      } else {
        return _col;
      }
    }) as TableProps["cols"];
  };
  $: baseFetchUrl = () => {
    return listFetchUrl({
      getUrl: getUrl(),
      tenant: tenant,
      product: product,
    });
  };
  $: tablePropsComputed = () => {
    return {
      ...tableProps,
      classNames: {
        ...tableProps?.classNames,
        iconSpan: defaultClasses.iconSpan,
      },
    };
  };

  let directoryListData = DEFAULT_VALUES.directoryListData;
  let isDirectoryListLoading = true;
  let pageTokenMap = {};
  let showErrorComponent = false;
  let errorMessage = "";

  function onUpdateFn_0(..._args: any[]) {
    if (!isPaginated()) {
      getFieldsData(baseFetchUrl());
    }
  }

  $: onUpdateFn_0(...[baseFetchUrl(), isPaginated()]);
</script>

<LoadingContainer isBusy={isDirectoryListLoading}>
  {#if isPaginated()}
    <Paginate
      itemsPerPage={paginate.itemsPerPage}
      currentPageItemsCount={directoryListData.length}
      handlePageChange={paginate?.handlePageChange}
      {reFetch}
      {pageTokenMap}
      ><PaginatedTable
        emptyStateMessage="No directories found."
        cols={colsToDisplay()}
        data={directoryListData}
        actions={actions()}
        {showErrorComponent}
        {errorMessage}
        tableProps={tablePropsComputed()}
      /></Paginate
    >
  {/if}
  {#if !isPaginated()}
    <NonPaginatedTable
      emptyStateMessage="No directories found."
      cols={colsToDisplay()}
      data={directoryListData}
      actions={actions()}
      {showErrorComponent}
      {errorMessage}
      tableProps={tablePropsComputed()}
    />
  {/if}</LoadingContainer
>