/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useEffect } from 'react';

import type { APIOptions } from '../../utils/types';

import { useGridlerStore } from '../GridlerStore';

//The computer component does not need to be recalculated on every render, so we use React.memo to prevent unnecessary re-renders.
export const GlidlerAPIAdaptorForGoLangv2 = React.memo((props: APIOptions) => {
  const [setStateFN, setState, getState, addError, mounted] = useGridlerStore((s) => [
    s.setStateFN,
    s.setState,
    s.getState,
    s.addError,
    s.mounted,
  ]);

  const useAPIQuery: (index: number) => Promise<any> = async (index: number) => {
    const colSort = getState('colSort');
    const pageSize = getState('pageSize');
    const colFilters = getState('colFilters');
    const _active_requests = getState('_active_requests');
    setState('loadingData', true);
    try {
      //console.log('APIAdaptorGoLangv2', { _active_requests, index, pageSize, props });
      if (props && props.url) {
        const head = new Headers();
        head.set('x-limit', String(pageSize ?? 50));
        head.set('x-offset', String((pageSize ?? 50) * index));

        head.set('Authorization', `Token ${props.authtoken}`);

        if (colSort?.length && colSort.length > 0) {
          head.set(
            'x-sort',
            colSort
              ?.map((sort: any) => `${sort.id} ${sort.direction}`)
              .reduce((acc: any, val: any) => `${acc},${val}`)
          );
        }

        if (colFilters?.length && colFilters.length > 0) {
          colFilters
            ?.filter((f) => f.value?.length > 0)
            ?.forEach((filter: any) => {
              if (filter.value && filter.value !== '') {
                head.set(`x-searchop-${filter.operator}-${filter.id}`, `${filter.value}`);
              }
            });
        }

        const currentRequestIndex = _active_requests?.findIndex((f) => f.page === index) ?? -1;
        _active_requests?.forEach((r) => {
          if ((r.page >= 0 && r.page < index - 2) || (index >= 0 && r.page > index + 2)) {
            r.controller?.abort?.();
          }
        });
        if (_active_requests && currentRequestIndex >= 0 && _active_requests[currentRequestIndex]) {
          //console.log(`Already queued ${index}`, index, s._active_requests);
          setState('loadingData', false);
          return undefined;
        }

        const controller = new AbortController();
        await setStateFN('_active_requests', (cv) => [...(cv ?? []), { controller, page: index }]);

        const res = await fetch(
          `${props.url}?x-limit=${String(pageSize ?? 50)}&x-offset=${String((pageSize ?? 50) * index)}`,
          {
            headers: head,
            method: 'GET',
            signal: controller?.signal,
          }
        );

        if (res.ok) {
          const cr = res.headers.get('Content-Range')?.split('/');
          if (cr?.[1] && parseInt(cr[1], 10) > 0) {
            setState('total_rows', parseInt(cr[1], 10));
          }

          const data = await res.json();
          setState('loadingData', false);
          return data ?? [];
        }
        addError(`${res.status} ${res.statusText}`, 'api', props.url);

        await setStateFN('_active_requests', (cv) => [
          ...(cv ?? []).filter((f) => f.page !== index),
        ]);
      }
    } catch (e) {
      //console.log('APIAdaptorGoLangv2 error', e);
      addError(`Error: ${e}`, 'api', props.url);
    }
    setState('loadingData', false);
    return [];
  };

  const askAPIRowNumber: (key: string) => Promise<number> = async (key: string) => {
    const colFilters = getState('colFilters');

    //console.log('APIAdaptorGoLangv2', { _active_requests, index, pageSize, props });
    if (props && props.url) {
      const head = new Headers();
      head.set('x-limit', '10');
      head.set('x-fetch-rownumber', String(key));

      head.set('Authorization', `Token ${props.authtoken}`);

      if (colFilters?.length && colFilters.length > 0) {
        colFilters
          ?.filter((f) => f.value?.length > 0)
          ?.forEach((filter: any) => {
            if (filter.value && filter.value !== '') {
              head.set(`x-searchop-${filter.operator}-${filter.id}`, `${filter.value}`);
            }
          });
      }

      const controller = new AbortController();

      const res = await fetch(`${props.url}?x-fetch-rownumber=${key}}`, {
        headers: head,
        method: 'GET',
        signal: controller?.signal,
      });

      if (res.ok) {
        const data = await res.json();

        return data?.[0]?._rownumber ?? data?._rownumber ?? 0;
      }
      addError(`${res.status} ${res.statusText}`, 'api', props.url);
    }
    return [];
  };

  useEffect(() => {
    setState('useAPIQuery', useAPIQuery);
    setState('askAPIRowNumber', askAPIRowNumber);
  }, [props.url, props.authtoken, mounted, setState]);

  return <></>;
});

GlidlerAPIAdaptorForGoLangv2.displayName = 'Gridler-GlidlerAPIAdaptorForGoLangv2';
