import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { BreadcrumbService } from '@core/breadcrumb';
import { CacheService } from '@core/cache';
import { Config } from '@core/config';
import { DomainRemissionService } from '@domain/remission';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ReturnDTO } from '@swagger/remi';
import { NEVER, Observable } from 'rxjs';
import { catchError, filter, first, map, shareReplay, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { ShortReceiptNumberPipe } from '../../pipes/short-receipt-number.pipe';
import { RemissionListComponentStore } from '../../remission-list/remission-list.component-store';

export interface ShippingDocumentDetailsState {
  remissionStarted?: boolean;
  return: ReturnDTO;
}

@Component({
  selector: 'page-shipping-document-details',
  templateUrl: 'shipping-document-details.component.html',
  styleUrls: ['shipping-document-details.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [ShortReceiptNumberPipe],
})
export class ShippingDocumentDetailsComponent extends ComponentStore<ShippingDocumentDetailsState> implements OnInit {
  get processId() {
    return this._config.get('process.ids.remission');
  }

  notCompleted$: Observable<boolean>;

  returnId$: Observable<number>;

  hasItems$: Observable<boolean>;

  firstReceiptId$: Observable<number>;

  finishShippingDocumentDisabled$: Observable<boolean>;

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

  get remissionStarted$() {
    return this.select((s) => s.remissionStarted).pipe(shareReplay());
  }

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

  get return$() {
    return this.select((s) => s.return).pipe(shareReplay());
  }

  scrollPosition$ = this._breadcrumb.getBreadcrumbsByKeyAndTags$(this.processId, ['remission']).pipe(
    map((crumbs) => {
      const crumbParams = crumbs?.find((_) => true)?.params;

      if (crumbParams && Object.keys(crumbParams)?.find((key) => key === 'scroll_position')) {
        return { scroll_position: crumbParams['scroll_position'] ?? 0 };
      } else {
        return {};
      }
    })
  );

  queryParams$ = this.scrollPosition$.pipe(
    withLatestFrom(this._activatedRoute.queryParams),
    map(([scrollPosition, queryParams]) => {
      return { ...queryParams, ...scrollPosition };
    })
  );

  constructor(
    private _remissionListStore: RemissionListComponentStore,
    private _activatedRoute: ActivatedRoute,
    private _remissionService: DomainRemissionService,
    private _breadcrumb: BreadcrumbService,
    private _config: Config,
    private _shortReceiptNumberPipe: ShortReceiptNumberPipe,
    private _router: Router,
    private _cache: CacheService
  ) {
    super({ return: undefined });
  }

  ngOnInit() {
    this.removeBreadcrumbs();
    this.getReturn();

    this.finishShippingDocumentDisabled$ = this.return$.pipe(
      map((returnDto) => returnDto?.receipts?.find((_) => true)?.data?.items?.length === 0)
    );

    this.firstReceiptId$ = this.return$.pipe(map((returnDto) => returnDto?.receipts?.find((_) => true)?.data?.id));

    this.notCompleted$ = this.return$.pipe(map((returnDto) => !returnDto?.completed && !this.remissionStarted));

    this.returnId$ = this.return$.pipe(map((returnDto) => returnDto?.id));

    this.hasItems$ = this.return$.pipe(map((returnDto) => returnDto?.receipts?.find((_) => true)?.data?.items?.length > 0));
  }

  removeBreadcrumbs() {
    this._breadcrumb.removeBreadcrumbsByKeyAndTags(this.processId, ['remission', 'add-product']);
    this._breadcrumb.removeBreadcrumbsByKeyAndTags(this.processId, ['remission', 'create']);
    this._breadcrumb.removeBreadcrumbsByKeyAndTags(this.processId, ['remission', 'finish-shipping-document']);
    this._breadcrumb.removeBreadcrumbsByKeyAndTags(this.processId, ['remission', 'finish-remission']);
  }

  async navigateBack() {
    const queryParams = await this.queryParams$.pipe(first()).toPromise();
    this.remissionStarted
      ? this._router.navigate(['../list'], { relativeTo: this._activatedRoute, queryParams })
      : this._router.navigate(['..'], { relativeTo: this._activatedRoute });
  }

  async addOrUpdateBreadcrumbIfNotExists(returnDto: ReturnDTO) {
    const packageNumber = returnDto?.receipts?.find((_) => true)?.data?.receiptNumber;
    const params = await this.queryParams$.pipe(first()).toPromise();
    if (packageNumber) {
      const shortPackageNumber = this._shortReceiptNumberPipe.transform(packageNumber);
      this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
        key: this.processId,
        name: `${this.remissionStarted ? `Warenbegleitschein #${shortPackageNumber}` : `#${shortPackageNumber}`}`,
        path: this.remissionStarted
          ? `/filiale/remission/${returnDto.id}/shipping-document`
          : `/filiale/remission/shipping-documents/${returnDto.id}`,
        section: 'branch',
        params,
        tags: ['remission', 'shipping-documents', 'details'],
      });
    }
  }

  deleted() {
    // Cache leeren und Reload bei Wechsel zurück zur Liste triggern
    this._remissionListStore.clearCache();
    this._remissionListStore._triggerReload$.next(true);

    this.navigateBack();
  }

  itemDeleted() {
    // Cache leeren und Reload bei Wechsel zurück zur Liste triggern
    this._remissionListStore.clearCache();
    this._remissionListStore._triggerReload$.next(true);

    this.reloadReturn();
  }

  reloadReturn = this.effect(($) =>
    $.pipe(
      tap((_) => {
        this._cache.delete({ processId: String(this.processId) });
        this.getReturn();
      })
    )
  );

  getReturn = this.effect(($) =>
    $.pipe(
      withLatestFrom(this._activatedRoute.params),
      tap(([_, params]) =>
        params?.id ? this.patchState({ remissionStarted: false }) : params?.returnId ? this.patchState({ remissionStarted: true }) : ''
      ),
      map(([_, params]) => params?.id ?? params?.returnId),
      filter((id) => !!id),
      switchMap((id) => this._remissionService.getReturn(id)),
      tapResponse(
        (r: ReturnDTO) => {
          this.setReturn(r);
          this.addOrUpdateBreadcrumbIfNotExists(r);
        },
        (err) => {
          this.navigateBack();
          return NEVER;
        }
      ),
      catchError(() => {
        this.navigateBack();
        return NEVER;
      })
    )
  );

  setReturn = this.updater<ReturnDTO>((state, r) => ({
    ...state,
    return: r,
  }));
}
