import { inject, Injectable } from '@angular/core';

import { Action, Selector, State, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

import { ICategory } from '../../shared/interface/category.interface';
import {
  GetCategoriesAction,
  GetCategoryBySlugAction,
  GetSearchByCategoryAction,
} from '../action/category.action';
import { CategoryService } from '../services/category.service';

export class CategoryStateModel {
  category = {
    data: [] as ICategory[],
    total: 0,
  };
  searchByCategory: ICategory[];
  selectedCategory: ICategory | null;
}

@State<CategoryStateModel>({
  name: 'category',
  defaults: {
    category: {
      data: [],
      total: 0,
    },
    searchByCategory: [],
    selectedCategory: null,
  },
})
@Injectable()
export class CategoryState {
  private categoryService = inject(CategoryService);

  @Selector()
  static category(state: CategoryStateModel) {
    return state.category;
  }

  @Selector()
  static searchByCategory(state: CategoryStateModel) {
    return state.searchByCategory;
  }

  @Selector()
  static selectedCategory(state: CategoryStateModel) {
    return state.selectedCategory;
  }

  @Action(GetCategoriesAction)
  getCategories(ctx: StateContext<CategoryStateModel>, action: GetCategoriesAction) {
    return this.categoryService.getCategories(action.payload).pipe(
      tap({
        next: result => {
          ctx.patchState({
            category: {
              data: result.data,
              total: result?.total ? result?.total : result.data.length,
            },
          });
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(GetSearchByCategoryAction)
  getSearchByCategory(ctx: StateContext<CategoryStateModel>, action: GetSearchByCategoryAction) {
    this.categoryService.searchSkeleton = true;
    return this.categoryService.getCategories(action.payload).pipe(
      tap({
        next: result => {
          ctx.patchState({
            searchByCategory: result ? result?.data : [],
          });
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
        complete: () => {
          this.categoryService.searchSkeleton = false;
        },
      }),
    );
  }

  @Action(GetCategoryBySlugAction)
  getCategoryBySlug(ctx: StateContext<CategoryStateModel>, action: GetCategoryBySlugAction) {
    return this.categoryService.getCategoryBySlug(action.slug).pipe(
      tap({
        next: result => {
          const state = ctx.getState();
          ctx.patchState({
            ...state,
            selectedCategory: result,
          });
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }
}
