<script lang="ts">
  import type {
    ConnectionData,
    ConnectionListProps,
    OIDCSSORecord,
    SAMLSSORecord,
  } from "../types";
  import LoadingContainer from "../../../shared/LoadingContainer/index.svelte";
  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 = {
    isSettingsView: false,
    connectionListData: [] as ConnectionData<any>[],
  };

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

  function connectionProviderName(connection: SAMLSSORecord | OIDCSSORecord) {
    if ("idpMetadata" in connection) {
      return (
        connection.idpMetadata.friendlyProviderName ||
        connection.idpMetadata.provider
      );
    }
    if ("oidcProvider" in connection) {
      return (
        connection.oidcProvider.friendlyProviderName ||
        connection.oidcProvider.provider
      );
    }
    return "Unknown";
  }
  function listFetchUrl(
    params: Partial<PaginatePayload> &
      Pick<ConnectionListProps, "tenant" | "product" | "displaySorted"> & {
        getUrl: string;
      }
  ) {
    let _url = params.getUrl;
    const [urlPath, qs] = _url.split("?");
    const urlParams = new URLSearchParams(qs);
    if (params.tenant) {
      if (Array.isArray(params.tenant)) {
        for (const _tenant of params.tenant) {
          urlParams.append("tenant", _tenant);
        }
      } else {
        urlParams.set("tenant", params.tenant);
      }
    }
    if (params.product) {
      urlParams.set("product", params.product);
    }
    if (params.pageToken) {
      urlParams.set("pageToken", params.pageToken);
    }
    if (params.displaySorted) {
      urlParams.set("sort", "true");
    }
    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(url: string) {
    isConnectionListLoading = true;
    type ConnectionList = ConnectionData<SAMLSSORecord | OIDCSSORecord>[];
    const response = await sendHTTPRequest<
      | ConnectionList
      | {
          data: ConnectionList;
          pageToken: PageToken;
        }
    >(url);
    isConnectionListLoading = 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 {
        const isTokenizedPagination =
          typeof response === "object" && "pageToken" in response;
        const _data = isTokenizedPagination ? response.data : response;
        if (Array.isArray(_data)) {
          const _connectionsListData = _data.map(
            (connection: ConnectionData<any>) => {
              return {
                ...connection,
                provider: connectionProviderName(connection),
                type: "oidcProvider" in connection ? "OIDC" : "SAML",
                status: connection.deactivated ? "Inactive" : "Active",
                isSystemSSO: connection.isSystemSSO,
              };
            }
          );
          connectionListData = _connectionsListData;
          typeof handleListFetchComplete === "function" &&
            handleListFetchComplete(_connectionsListData);
        }
        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);
    }
  }
  $: getUrl = () => {
    return urls.get;
  };
  $: isPaginated = () => {
    return paginate?.itemsPerPage !== undefined;
  };
  $: colsToDisplay = () => {
    return (
      cols || [
        "name",
        "provider",
        "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 if (_col === "name") {
        return {
          name: "name",
          badge: {
            position: "right",
            badgeText: "System",
            variant: "info",
            shouldDisplayBadge(rowData) {
              return rowData.isSystemSSO;
            },
          },
        };
      } else {
        return _col;
      }
    }) as TableProps["cols"];
  };
  $: actions = () => {
    return [
      {
        icon: "PencilIcon",
        label: "Edit",
        handleClick: (connection: ConnectionData<any>) =>
          handleActionClick("edit", connection),
      },
    ];
  };
  $: baseFetchUrl = () => {
    return listFetchUrl({
      getUrl: getUrl(),
      tenant: tenant,
      product: product,
      displaySorted: displaySorted,
    });
  };

  let connectionListData = DEFAULT_VALUES.connectionListData;
  let isConnectionListLoading = true;
  let pageTokenMap = {};
  let showErrorComponent = false;
  let errorMessage = "";

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

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

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