import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { filter, map, distinctUntilChanged, shareReplay, take, withLatestFrom, first } from 'rxjs/operators';
import { isNullOrUndefined } from 'util';
import { ShelfEditFormService } from '../../services';
import { FormGroup, FormArray } from '@angular/forms';
import { ProcessingStatusPipe, PickUpDateOptionsToDisplayValuesPipe, ProcessingStatusOptionsPipe } from '../../pipes';
import { DatePipe } from '@angular/common';
import { ShelfNavigationService } from '../../shared/services';
import { OrderItemProcessingStatusValue } from '@swagger/oms';
import { ErrorService } from 'apps/sales/src/app/core/error/component/error.service';

@Component({
  selector: 'app-shelf-edit-compartment',
  templateUrl: 'shelf-edit-compartment.component.html',
  styleUrls: ['./shelf-edit-compartment.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShelfEditCompartmentComponent implements OnInit {
  // Form Information
  customerName: { firstName: string; lastName: string };
  form: FormGroup;
  items: FormArray;

  // Pipes for Mapping Values to display names
  processingStatusPipe = new ProcessingStatusPipe();
  processingStatusOptionsPipe = new ProcessingStatusOptionsPipe();
  dateOptionsPipe = new PickUpDateOptionsToDisplayValuesPipe();
  datePipe = new DatePipe('de');

  constructor(
    private activatedRoute: ActivatedRoute,
    protected formService: ShelfEditFormService,
    private shelfNavigationService: ShelfNavigationService,
    private errorService: ErrorService,
    private cdr: ChangeDetectorRef
  ) {}

  get compartmentCode$(): Observable<string> {
    return this.activatedRoute.params.pipe(
      filter((params) => !isNullOrUndefined(params)),
      map((params) => params.compartmentCode),
      distinctUntilChanged(),
      shareReplay()
    );
  }

  get processingStatus$() {
    return this.activatedRoute.params.pipe(
      map((params) => Number(params.processingStatus) as OrderItemProcessingStatusValue),
      distinctUntilChanged(),
      shareReplay()
    );
  }

  ngOnInit() {
    this.loadCompartmentAndInitForm();
  }

  async loadCompartmentAndInitForm() {
    const compartmentCode = await this.compartmentCode$.pipe(take(1)).toPromise();
    const processingStatus = await this.processingStatus$.pipe(take(1)).toPromise();

    this.populateFormData(compartmentCode, processingStatus);
  }

  async onSubmit() {
    const compartmentCode = await this.compartmentCode$.pipe(first()).toPromise();
    const processingStatus = await this.processingStatus$.pipe(first()).toPromise();
    const submitResult = await this.formService.submit(this.form, processingStatus);

    let newValues: {
      orderNumber?: string;
      compartmentCode?: string;
      processingStatus?: number;
    };
    if (submitResult.result) {
      newValues = {
        compartmentCode: this.form.get('compartmentCode').value || compartmentCode,
        processingStatus: this.form.get('processingStatus').value || processingStatus,
      };

      this.shelfNavigationService.navigateBackToDetails(newValues, {
        compartmentCode,
        processingStatus,
      });
    }

    if (!submitResult.result) {
      this.showSubmitError({
        message: submitResult.message,
        code: submitResult.http ? submitResult.http.code : 500,
        invalidProperties: submitResult.errorReasons,
      });
    }
  }

  onAbortEdit() {
    return this.compartmentCode$.pipe(take(1), withLatestFrom(this.processingStatus$)).subscribe(([compartmentCode, processingStatus]) =>
      this.shelfNavigationService.navigateBackToDetails({
        compartmentCode,
        processingStatus,
      })
    );
  }

  private async populateFormData(compartmentCode: string, processingStatus: OrderItemProcessingStatusValue) {
    this.form = await this.formService.createFormByCompartmentCode(compartmentCode, processingStatus);
    this.items = this.formService.getItemsForm(compartmentCode);
    this.customerName = this.formService.getCustomerName(compartmentCode);
    this.cdr.detectChanges();
  }

  private showSubmitError(error: { message: string; code: number; invalidProperties: { [key: string]: string } }) {
    const invalidProperties = Object.values(error.invalidProperties).join(', ') || undefined;

    this.errorService.addErrors(error.code, error.message, invalidProperties);
  }
}
