import { createSyncStore } from '@warkypublic/zustandsyncstore';
import { produce } from 'immer';

import type { BoxerProps, BoxerStoreState } from './Boxer.types';

const { Provider: BoxerProvider, useStore: useBoxerStore } = createSyncStore<
  BoxerStoreState,
  BoxerProps
>(
  (set, get) => ({
    boxerData: [],
    // Data Actions
    fetchData: async (search?: string, reset?: boolean) => {
      const state = get();

      // Handle local data
      if (state.dataSource === 'local' || !state.onAPICall) {
        const localData = state.data ?? [];

        if (!search) {
          set({ boxerData: localData, hasMore: false, total: localData.length });
          return;
        }

        // Filter local data based on search
        const filtered = localData.filter((item) =>
          item.label.toLowerCase().includes(search.toLowerCase())
        );
        set({ boxerData: filtered, hasMore: false, total: filtered.length });
        return;
      }

      // Handle server-side data
      if (state.onAPICall) {
        try {
          set({ isFetching: true });

          const currentPage = reset ? 0 : state.page;

          const result = await state.onAPICall({
            page: currentPage,
            pageSize: state.pageSize,
            search,
          });

          set(
            produce((draft) => {
              if (reset) {
                draft.boxerData = result.data;
                draft.page = 0;
              } else {
                draft.boxerData = [...(draft.boxerData ?? []), ...result.data];
              }
              draft.total = result.total;
              draft.hasMore = draft.boxerData.length < result.total;
              draft.isFetching = false;
            })
          );
        } catch (error) {
          console.error('Boxer fetchData error:', error);
          set({ isFetching: false });
        }
      }
    },
    fetchMoreOnBottomReached: (target: HTMLDivElement) => {
      const state = get();

      if (!state.hasMore || state.isFetching) {
        return;
      }

      const scrollPercentage =
        (target.scrollTop + target.clientHeight) / target.scrollHeight;

      // Load more when scrolled past 80%
      if (scrollPercentage > 0.8) {
        state.loadMore();
      }
    },
    // State Management
    getState: (key) => {
      const current = get();
      return current?.[key];
    },
    hasMore: true,
    input: '',
    isFetching: false,
    loadMore: async () => {
      const state = get();

      if (!state.hasMore || state.isFetching) {
        return;
      }

      set(
        produce((draft) => {
          draft.page = draft.page + 1;
        })
      );

      await state.fetchData(state.search);
    },
    // Initial State
    opened: false,
    page: 0,

    pageSize: 50,

    search: '',

    selectedOptionIndex: -1,

    setInput: (input: string) => {
      set({ input });
    },

    // Actions
    setOpened: (opened: boolean) => {
      set({ opened });
    },

    setSearch: (search: string) => {
      set({ search });
    },

    setSelectedOptionIndex: (index: number) => {
      set({ selectedOptionIndex: index });
    },

    setState: (key, value) => {
      set(
        produce((state) => {
          state[key] = value;
        })
      );
    },

    total: 0,
  }),
  ({
    data = [],
    dataSource = 'local',
    pageSize = 50,
    ...props
  }) => {
    return {
      ...props,
      boxerData: data, // Initialize with local data if provided
      data,
      dataSource,
      hasMore: dataSource === 'server',
      pageSize,
      total: data.length,
    };
  }
);

export { BoxerProvider };
export { useBoxerStore };
