import {
  Component,
  OnInit,
  ChangeDetectionStrategy,
  OnDestroy,
} from '@angular/core';
import { Observable, Subject, BehaviorSubject } from 'rxjs';
import { SetAllExistingRemissions } from 'apps/sales/src/app/core/store/actions/remission.actions';
import { Store, Select } from '@ngxs/store';
import { isNullOrUndefined } from 'util';
import { filter, takeUntil, map, take } from 'rxjs/operators';
import { RemissionSelectors } from 'apps/sales/src/app/core/store/selectors/remission.selectors';
import { Router } from '@angular/router';
import { AddBreadcrumb } from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
import { SetBranchProcessCurrentPath } from 'apps/sales/src/app/core/store/actions/branch-process.actions';
import { ErrorService } from 'apps/sales/src/app/core/error/component/error.service';
import { ShippingDocumentNumberFormatterPipe } from 'apps/sales/src/app/pipes/shipping-document-number-formatter.pipe';
import { PackageNumberParserPipe } from 'apps/sales/src/app/pipes/package-number-parser.pipe';
import { RemissionProcess, RemissionService } from '@isa/remission';

@Component({
  selector: 'app-remissions-overview',
  templateUrl: 'remissions-overview.component.html',
  styleUrls: ['./remissions-overview.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RemissionsOverviewComponent implements OnInit, OnDestroy {
  destroy$ = new Subject();
  isLoading = new BehaviorSubject<boolean>(true);

  @Select(RemissionSelectors.getAllRemissions)
  allRemissions$: Observable<RemissionProcess[]>;

  constructor(
    private remissionService: RemissionService,
    private store: Store,
    private router: Router,
    private errorService: ErrorService
  ) {}

  ngOnInit() {
    this.loadAllRemissions();
  }

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

  navigateToDetailsPage(externalRemissionId: number) {
    this.allRemissions$
      .pipe(
        takeUntil(this.destroy$),
        map((allRemissions) =>
          allRemissions.find(
            (remission) => remission.externalId === externalRemissionId
          )
        ),
        take(1)
      )
      .subscribe(this.openDetailsPage);
  }

  private getShippingDocument(remission: RemissionProcess) {
    return (
      (remission.shippingDocuments &&
        remission.shippingDocuments.find((sd) => !sd.isCompleted)) ||
      remission.shippingDocuments[0]
    );
  }

  private openDetailsPage = (remissionProcess: RemissionProcess) => {
    const shippingDocumentId = this.getShippingDocumentId(remissionProcess);
    const shippingDocumentNumber = this.getShippingDocumentNumber(
      remissionProcess
    );

    if (!shippingDocumentId) {
      this.errorService.addErrors(
        400,
        'Für den Vorgang existiert keine Warenbegleischein ID',
        'Warenbegleitschein ID unbekannt'
      );
    }

    const path = `remission/overview/${shippingDocumentId}`;
    this.store.dispatch(
      new AddBreadcrumb(
        {
          path: path,
          name: `Warenbegleitschein ${this.getFormattedShippingDocumentNumber(
            shippingDocumentNumber
          )}`,
        },
        'remission'
      )
    );
    this.store.dispatch(new SetBranchProcessCurrentPath(path, true));
    this.router.navigate([path]);
  };

  private loadAllRemissions() {
    this.remissionService
      .getAllRemissions({
        showOpen: true,
        showCompleted: true,
        showCompletedLastWeekOnly: true,
        take: 200,
      })
      .pipe(
        takeUntil(this.destroy$),
        filter((remissionProcesses) => !isNullOrUndefined(remissionProcesses))
      )
      .subscribe(
        this.allRemissionsSubscriptionHandler,
        this.handleRemissionLoadingError
      );
  }

  private handleRemissionLoadingError = (err: any) => {
    this.isLoading.next(false);
  };

  private allRemissionsSubscriptionHandler = (
    remissionProcesses: RemissionProcess[]
  ) => {
    this.store.dispatch(new SetAllExistingRemissions(remissionProcesses));
    this.isLoading.next(false);
  };

  private getShippingDocumentId = (remissionProcess: RemissionProcess) => {
    if (!this.getShippingDocument(remissionProcess)) {
      return null;
    }

    return this.getShippingDocument(remissionProcess).id;
  };

  private getShippingDocumentNumber = (remissionProcess: RemissionProcess) => {
    if (this.getShippingDocument(remissionProcess)) {
      return null;
    }

    return this.getShippingDocument(remissionProcess).shippingDocumentNumber;
  };

  private getFormattedShippingDocumentNumber(
    shippingDocumentNumber: string
  ): string {
    const numberFormatter = new ShippingDocumentNumberFormatterPipe();
    const numberParser = new PackageNumberParserPipe();

    return numberParser.transform(
      numberFormatter.transform(shippingDocumentNumber)
    );
  }
}
