import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { DomainGoodsService } from '@domain/oms';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';

import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO } from '@generated/swagger/oms-api';
import { isResponseArgs } from '@utils/object';
import { Subject } from 'rxjs';
import { switchMap, tap, withLatestFrom } from 'rxjs/operators';

export interface GoodsInRemissionPreviewState {
  message?: string;
  fetching: boolean;
  hits: number;
  results: OrderItemListItemDTO[];
}

@Injectable()
export class GoodsInRemissionPreviewStore extends ComponentStore<GoodsInRemissionPreviewState> {
  get results() {
    return this.get((s) => s.results);
  }
  readonly results$ = this.select((s) => s.results);

  get hits() {
    return this.get((s) => s.hits);
  }
  readonly hits$ = this.select((s) => s.hits);

  get fetching() {
    return this.get((s) => s.fetching);
  }
  readonly fetching$ = this.select((s) => s.fetching);

  private _searchResultSubject = new Subject<ListResponseArgsOfOrderItemListItemDTO>();

  readonly searchResult$ = this._searchResultSubject.asObservable();

  constructor(private _domainGoodsInService: DomainGoodsService) {
    super({
      fetching: false,
      hits: 0,
      results: [],
    });
  }

  createRemissionFromPreview() {
    return this._domainGoodsInService.createGoodsInRemissionFromPreviewList();
  }

  searchRequest() {
    return this._domainGoodsInService.goodsInRemissionPreviewList();
  }

  search = this.effect(($) =>
    $.pipe(
      tap((_) => this.patchState({ fetching: true })),
      withLatestFrom(this.results$),
      switchMap(([_, _results]) =>
        this.searchRequest().pipe(
          tapResponse(
            (res) => {
              this.patchState({
                hits: res.hits,
                results: res.result ?? [],
                fetching: false,
              });

              this._searchResultSubject.next(res);
            },
            (err: Error) => {
              if (err instanceof HttpErrorResponse && isResponseArgs(err.error)) {
                this._searchResultSubject.next(err.error);
              } else {
                this._searchResultSubject.next({
                  error: true,
                  message: err.message,
                });
              }
              this.patchState({ fetching: false });
              console.error('GoodsInRemissionPreview.search()', err);
            },
          ),
        ),
      ),
    ),
  );
}
