import { withStorageSync } from "@angular-architects/ngrx-toolkit";
import { computed, inject } from "@angular/core";
import { AppSetting } from "@core/domain-classes/app-setting";
import { CommonError } from "@core/error-handler/common-error";
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";
import { AppSettingService } from "@core/services/app-setting.service";

type AppsettingsState = {
  appSettings: AppSetting[];
  isLoading: boolean;
  filter: { key: string; value: string; orderField: string; order: 'asc' | 'desc' | '', name: string };
  commonError: CommonError
};

export const initialAppSettingState: AppsettingsState = {
  appSettings: [],
  isLoading: false,
  filter: { key: '', value: '', name: '', orderField: 'name', order: 'asc' },
  commonError: null
};

export const AppSettingsStore = signalStore(
  { providedIn: 'root' },
  withState(initialAppSettingState),
  withStorageSync({
    key: 'appestings', // 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(({ appSettings, filter }) => ({
    sortedFilteredAppSettings: computed(() => {
      const direction = filter.order() === 'asc' ? 1 : -1;
      const filterFields = ['key', 'value', 'name']; // Add more fields as needed
      let filterAppSettings = appSettings().filter((appsetting) => {
        return filterFields.every(field => {
          const filterValue = filter[field]();
          return !filterValue || appsetting[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 filterAppSettings.sort(multiFieldSort);
    }),

  })),
  withMethods((store, appSettingsService = inject(AppSettingService),
    toastrService = inject(ToastrService),
    translationService = inject(TranslationService)) => ({
      loadByQuery: rxMethod<void>(
        pipe(
          debounceTime(300),
          tap(() => patchState(store, { isLoading: true })),
          switchMap(() => {
            return appSettingsService.getAppSettings().pipe(
              tapResponse({
                next: (appSettings: AppSetting[]) => {
                  patchState(store, { appSettings: [...appSettings], isLoading: false, commonError: null })
                },
                error: (err: CommonError) => {
                  patchState(store, { commonError: err, isLoading: false });
                  console.error(err);
                },
              })
            );
          })
        )
      ),
      deleteAppSettingsById: rxMethod<string>(
        pipe(
          distinctUntilChanged(),
          tap(() => patchState(store, { isLoading: true })),
          switchMap((appSettingId: string) => {
            return appSettingsService.deleteAppSetting(appSettingId).pipe(
              tapResponse({
                next: () => {
                  toastrService.success(translationService.getValue('APPSETTING_DELETED'));
                  patchState(store, { appSettings: store.appSettings().filter(c => c.id != appSettingId), isLoading: false })
                },
                error: (err: CommonError) => {
                  patchState(store, { commonError: err, isLoading: false });
                  console.error(err);
                },
              })
            );
          })
        )
      ),
      sortFilterAppsettings(order: 'asc' | 'desc' | '', orderField: string = '', key: string = '', value: string = '', name: string = '') {
        patchState(store, { filter: { key: key, value: value, orderField: orderField, order: order, name: name } });
      },
    })),
  withHooks({
    onInit(store) {
      if (sessionStorage.getItem('appestings')) {
        return;
      }
      store.loadByQuery();
    },

  }),
);
