import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core';
import { CommandService } from '@core/command';
import { DomainOmsService } from '@domain/oms';
import { ComponentStore } from '@ngrx/component-store';
import { OrderItemListItemDTO, StockStatusCodeDTO } from '@swagger/oms';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { isEqual } from 'lodash';
import { Observable, Subject } from 'rxjs';
import { catchError, first, map, shareReplay, switchMap } from 'rxjs/operators';

interface GoodsInListItemComponentState {
  item: OrderItemListItemDTO;
  editSsc: boolean;
  sscInvalid: boolean;
  sscChanged: boolean;
  ssc: string;
  sscText: string;
  supplierIdError: boolean;
}

@Component({
  selector: 'goods-in-list-item',
  templateUrl: 'goods-in-list-item.component.html',
  styleUrls: ['goods-in-list-item.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComponentState> implements OnDestroy {
  @Output() refresh = new EventEmitter<void>();

  @Input()
  get item() {
    return this.get((s) => s.item);
  }
  set item(item: OrderItemListItemDTO) {
    if (!isEqual(this.item, item)) {
      if (!item.supplierId) {
        this.patchState({ supplierIdError: true });
      }

      this.patchState({ item });

      if (item.ssc && item.sscText) {
        this.ssc = item.ssc;
        this.sscText = item.sscText;
      }
    }
  }
  readonly item$ = this.select((s) => s.item);

  @Input()
  get editSsc() {
    return this.get((s) => s.editSsc);
  }
  set editSsc(editSsc: boolean) {
    if (this.editSsc !== editSsc) {
      this.patchState({ editSsc });
    }
  }
  readonly editSsc$ = this.select((s) => s.editSsc);

  get sscInvalid() {
    return this.get((s) => s.sscInvalid);
  }
  set sscInvalid(sscInvalid: boolean) {
    if (this.sscInvalid !== sscInvalid) {
      this.patchState({ sscInvalid });
    }
  }
  readonly sscInvalid$ = this.select((s) => s.sscInvalid).pipe(shareReplay());

  get sscChanged() {
    return this.get((s) => s.sscChanged);
  }
  set sscChanged(sscChanged: boolean) {
    if (this.sscChanged !== sscChanged) {
      this.patchState({ sscChanged });
    }
  }
  readonly sscChanged$ = this.select((s) => s.sscChanged);

  get ssc() {
    return this.get((s) => s.ssc);
  }
  set ssc(ssc: string) {
    if (this.ssc !== ssc) {
      this.patchState({ ssc });
    }
  }
  readonly ssc$ = this.select((s) => s.ssc);

  get sscText() {
    return this.get((s) => s.sscText);
  }
  set sscText(sscText: string) {
    if (this.sscText !== sscText) {
      this.patchState({ sscText });
    }
  }
  readonly sscText$ = this.select((s) => s.sscText);

  readonly supplierIdError$ = this.select((s) => s.supplierIdError);

  readonly statusCodes$: Observable<StockStatusCodeDTO[]> = this.item$.pipe(
    switchMap((item) => {
      if (item.supplierId) {
        return this._omsService.getStockStatusCodes({ supplierId: item.supplierId, eagerLoading: 2 });
      }
      this.patchState({ supplierIdError: true });
    }),
    catchError(() => {
      this.patchState({ supplierIdError: true });
      return [undefined];
    })
  );

  readonly instruction$ = this.statusCodes$.pipe(
    map((statusCodes) => {
      const code = statusCodes?.find((statusCode) => statusCode?.code === this.item.ssc);
      const textObj = code?.texts?.find((text) => text?.textType === 'REWORK');
      return textObj && textObj.text ? textObj.text : '';
    }),
    shareReplay()
  );

  private _onDestroy$ = new Subject();

  constructor(private _omsService: DomainOmsService, private _command: CommandService, private _modal: UiModalService) {
    super({
      item: undefined,
      editSsc: false,
      sscInvalid: false,
      sscChanged: false,
      ssc: undefined,
      sscText: undefined,
      supplierIdError: false,
    });
  }

  ngOnDestroy() {
    this._onDestroy$.next();
    this._onDestroy$.complete();
  }

  async sscChange(value: string) {
    this.ssc = value;
    this.sscChanged = true;

    const code = (await this.statusCodes$.pipe(first()).toPromise())?.find((statusCode) => statusCode.code === value);
    if (!!code) {
      this.sscText = code.supplierDescription;
      this.sscInvalid = false;
    } else {
      this.sscText = 'Meldenummer ist ungültig';
      this.sscInvalid = true;
    }
  }

  sscUpdated() {
    this.sscText = this.item.sscText;
    this.ssc = this.item.ssc;
    this.sscInvalid = false;
    this.sscChanged = false;
  }

  async showReorderModal() {
    try {
      await this._command.handleCommand('REORDER', { items: [this.item] });
      this.refresh.emit();
    } catch (e) {
      this._modal.open({
        content: UiErrorModalComponent,
        data: e,
      });
    }
  }
}
