import { withStorageSync } from "@angular-architects/ngrx-toolkit";
import { computed, inject } from "@angular/core";
import { Page } from "@core/domain-classes/page";
import { CommonError } from "@core/error-handler/common-error";
import { PageService } from "@core/services/page.service";
import { TranslationService } from "@core/services/translation.service";
import { tapResponse } from "@ngrx/operators";
import { patchState, signalStore, withComputed, withHooks, withMethods, withState } from "@ngrx/signals";
import { rxMethod } from "@ngrx/signals/rxjs-interop";
import { ToastrService } from "ngx-toastr";
import { debounceTime, distinctUntilChanged, pipe, switchMap, tap } from "rxjs";

type PageState = {
  pages: Page[];
  isLoading: boolean;
  filter: { url: string, name: string, orderField: string, order: 'asc' | 'desc' | '' };
  commonError: CommonError
};
export const initialPageState: PageState = {
  pages: [],
  isLoading: false,
  filter: { url: '', name: '', orderField: 'name', order: 'asc' },
  commonError: null
};
export const PageStore = signalStore(
  { providedIn: 'root' },
  withState(initialPageState),
  withStorageSync({
    key: 'pages', // key used when writing to/reading from storage
    autoSync: true, // read from storage on init and write on state changes - `true` by default
    storage: () => sessionStorage,
    // factory to select storage to sync with
  }),
  withComputed(({ pages, filter }) => ({
    sortedFilteredPages: computed(() => {
      const direction = filter.order() === 'asc' ? 1 : -1;
      const filterFields = ['url', 'name']; // Add more fields as needed
      let filterPages = pages().filter((page) => {
        return filterFields.every(field => {
          const filterValue = filter[field]();
          return !filterValue || page[field].toLocaleLowerCase().includes(filterValue.toLocaleLowerCase());
        });
      });
      const field = filter.orderField();
      const multiFieldSort = (a, b) => {
        const comparison = a[field].toLocaleLowerCase().localeCompare(b[field].toLocaleLowerCase());
        if (comparison !== 0) {
          return direction * comparison;
        }
        return 0;
      };
      return filterPages.sort(multiFieldSort);
    }),

  })),
  withMethods((store, pageService = inject(PageService),
    toastrService = inject(ToastrService),
    translationService = inject(TranslationService)) => ({
      loadByQuery: rxMethod<void>(
        pipe(
          debounceTime(300),
          tap(() => patchState(store, { isLoading: true })),
          switchMap(() => {
            return pageService.getAll().pipe(
              tapResponse({
                next: (pages: Page[]) => {
                  patchState(store, { pages: [...pages], isLoading: false, commonError: null })
                },
                error: (err: CommonError) => {
                  patchState(store, { commonError: err, isLoading: false });
                  console.error(err);
                },
              })
            );
          })
        )
      ),
      deletePageById: rxMethod<string>(
        pipe(
          distinctUntilChanged(),
          tap(() => patchState(store, { isLoading: true })),
          switchMap((pageId: string) => {
            return pageService.delete(pageId).pipe(
              tapResponse({
                next: () => {
                  toastrService.success(translationService.getValue('PAGE_DELETED_SUCCESSFULLY'));
                  patchState(store, { pages: store.pages().filter(c => c.id != pageId), isLoading: false })
                },
                error: (err: CommonError) => {
                  patchState(store, { commonError: err, isLoading: false });
                  console.error(err);
                },
              })
            );
          })
        )
      ),
      sortFilterPages(order: 'asc' | 'desc' | '', orderField: string = '', url: string = '', name: string = '') {
        patchState(store, { filter: { orderField: orderField, order: order, name: name, url: url } });
      },
    })),
  withHooks({
    onInit(store) {
      if (sessionStorage.getItem('pages')) {
        return;
      }
      store.loadByQuery();
    },
  }),
);
