import { inject, Injectable } from '@angular/core';
import { ComponentStore, OnStoreInit } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';

import { ItemDTO, ResponseArgsOfItemDTO } from '@generated/swagger/cat-search-api';
import { switchMap, withLatestFrom } from 'rxjs/operators';
import { Subject, asapScheduler } from 'rxjs';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainCatalogService } from '@domain/catalog';
import { AddToShoppingCartDTO, BranchDTO } from '@generated/swagger/checkout-api';
import { tap } from 'rxjs/operators';
import { UiModalService } from '@ui/modal';
import { KulturpassOrderModalStore } from '../kulturpass-order-modal.store';

export interface KulturpassOrderSearchboxState {
  query: string;
  fetching: boolean;
  branch?: BranchDTO;
}

@Injectable()
export class KulturpassOrderSearchboxStore
  extends ComponentStore<KulturpassOrderSearchboxState>
  implements OnStoreInit
{
  private _parentStore = inject(KulturpassOrderModalStore);
  private _catalogService = inject(DomainCatalogService);
  private _availabilityService = inject(DomainAvailabilityService);
  private _modal = inject(UiModalService);

  get query() {
    return this.get((s) => s.query);
  }

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

  get branch() {
    return this.get((s) => s.branch);
  }

  addToShoppingCart$ = new Subject<AddToShoppingCartDTO>();

  hint$ = new Subject<string>();

  constructor() {
    super({ query: '', fetching: false });
  }

  readonly query$ = this.select((state) => state.query);

  readonly updateQuery = this.updater((state, query: string) => ({ ...state, query }));

  readonly fetching$ = this.select((state) => state.fetching);

  readonly updateFetching = this.updater((state, fetching: boolean) => ({ ...state, fetching }));

  readonly branch$ = this.select((state) => state.branch);

  readonly updateBranch = this.updater((state, branch: BranchDTO) => ({ ...state, branch }));

  ngrxOnStoreInit = () => {
    this.loadBranch();
  };

  loadBranch = this.effect(($) =>
    $.pipe(
      switchMap(() =>
        this._availabilityService
          .getDefaultBranch()
          .pipe(tapResponse(this.handleBranchResponse, this.handleBranchError)),
      ),
    ),
  );

  handleBranchResponse = (res: BranchDTO) => {
    this.patchState({ branch: res });
  };

  handleBranchError = (err) => {
    this._modal.error('Fehler beim Laden der Filiale', err);
  };

  readonly search = this.effect(($) =>
    $.pipe(
      tap(() => this.patchState({ fetching: true })),
      withLatestFrom(this.query$),
      switchMap(([_, query]) =>
        this._catalogService
          .getDetailsByEan({ ean: query?.trim() })
          .pipe(tapResponse(this.handleSearchResponse, this.handleSearchError)),
      ),
    ),
  );

  handleSearchResponse = (res: ResponseArgsOfItemDTO) => {
    if (!res.result) {
      this.setHint('Artikel nicht gefunden');
      this.patchState({ fetching: false });
      return;
    }

    this._parentStore.canAddItem(res.result).add(() => {
      this.patchState({ query: '', fetching: false });
    });
  };

  handleSearchError = (err) => {
    this.setHint('Artikel nicht gefunden');
    this.patchState({ fetching: false });
  };

  setHint(hint: string) {
    this.hint$.next('');

    asapScheduler.schedule(() => {
      this.hint$.next(hint);
    }, 100);
  }
}
