import { Filter, WixPatternsContainerParams } from '@wix/bex-core';
import {
  Item,
  Query,
  QueryItemsRequest,
} from '@wix/bex-utils/@wix/ambassador-items-selection-spi-host-v1-provider/types';
import { queryItems } from '@wix/bex-utils/@wix/ambassador-items-selection-spi-host-v1-provider/http';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import { useFilterCollection } from '../useFilterCollection';

export type ItemsSelectionValue = Item & {
  id: string;
  name: string;
};

type FetchItemsFnResponse = {
  items: ItemsSelectionValue[];
  total?: number;
  cursor?: string | null;
};

type FetchItemsFn = (params: {
  providerKey: string;
  query: {
    search?: string;
    filters?: Query['filter'];
    limit: number;
    offset?: number;
    cursor?: string | null;
  };
  httpClient: WixPatternsContainerParams['httpClient'];
}) => Promise<FetchItemsFnResponse>;

function buildRequest(params: {
  query: {
    search?: string;
    limit: number;
    offset?: number;
    cursor?: string | null;
    filters?: Query['filter'];
  };
  providerKey: string;
}) {
  const { query, providerKey } = params;
  const resolvedQuery: Query =
    query.cursor != null
      ? {
          cursorPaging: { cursor: query.cursor, limit: query.limit },
        }
      : query.offset != null && query.offset > 0
      ? {
          paging: {
            offset: query.offset,
            limit: query.limit,
          },
        }
      : {
          paging: { limit: query.limit, offset: 0 },
          cursorPaging: { limit: query.limit },
        };

  if (!query.cursor) {
    if (query.filters && Object.keys(query.filters).length > 0) {
      resolvedQuery.filter = { ...query.filters };
    }

    // According to the guidelines, we should not pass search query if cursor is present
    if (query.search) {
      resolvedQuery.search = query.search;
    }
  }

  const request: QueryItemsRequest = {
    providerKey,
    query: resolvedQuery,
  };

  return request;
}

// When we publish items-selection-code, we need to use this code from there and no to duplicate it here
const useQueryItems = () => {
  const {
    httpClient,
    errorHandler: { withErrorHandler },
    translate: t,
  } = useWixPatternsContainer();

  const fetchItems: FetchItemsFn = async ({ providerKey, query }) => {
    const request: QueryItemsRequest = buildRequest({
      query,
      providerKey,
    });

    const res = await withErrorHandler(
      () => httpClient.request(queryItems(request)),
      {
        PROVIDER_NOT_FOUND: () => ({
          message: t('cairo.provider-not-found.error'),
          action: {
            text: t('cairo.error.contactSupport.cta'),
            onClick: () => {},
          },
        }),
        QUERY_PROVIDER_ITEMS_FAILED: () => ({
          message: t('cairo.provider-not-found.error'),
          action: {
            text: t('cairo.error.contactSupport.cta'),
            onClick: () => {},
          },
        }),
      },
    );

    const { items, pagingMetadata } = res.data;
    return {
      items: (items as ItemsSelectionValue[]) || [],
      total: pagingMetadata?.total || 0,
      hasNext: pagingMetadata?.hasNext,
      cursor: pagingMetadata?.cursors?.next,
    };
  };

  return { fetchItems };
};

export interface UseItemsSelectionFilterParams {
  /**
   * The provider key to use for fetching items.
   */
  providerKey: string;
  /**
   * This is a reference to the filter that was defined in the main collection. For example: `collection.filters.<filterName>`.
   */
  filter: Filter<ItemsSelectionValue[]>;

  /**
   * Additional filters to apply to the query.
   */
  queryFilters?: Query['filter'];
}

export const useItemsSelectionFilter = ({
  providerKey,
  filter,
  queryFilters,
}: UseItemsSelectionFilterParams) => {
  const { httpClient } = useWixPatternsContainer();
  const { fetchItems } = useQueryItems();
  const renderItem = (item: ItemsSelectionValue) => ({
    title: item?.name ?? '',
    subtitle: item?.description ?? '',
  });

  const collection = useFilterCollection(filter, {
    queryName: providerKey,
    fetchData: async (query) => {
      const { items, ...res } = await fetchItems({
        providerKey,
        query: {
          ...query,
          filters: {
            ...(queryFilters || {}),
            ...query.filters,
          },
        },
        httpClient,
      });

      // initial pagination unknown, set to cursor if next cursor exists
      collection._paginationModeRef.current = res.cursor ? 'cursor' : 'offset';

      return {
        ...res,
        items,
      };
    },
    limit: 50,
  });

  return { collection, renderItem };
};
