import {
  Component,
  ChangeDetectionStrategy,
  ViewChild,
  ElementRef,
  HostListener,
  ChangeDetectorRef,
  ViewRef,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { Config } from '@core/config';
import { DomainPackageInspectionService } from '@domain/package-inspection';
import { ToasterService } from '@shared/shell';
import {
  ArrivalStatus,
  NestedKeyValueDTOOfStringAndString,
  PackageDetailResponseDTO,
} from '@generated/swagger/wws-api';
import { UiModalService } from '@ui/modal';
import { Observable, Subject } from 'rxjs';
import { first, map, shareReplay, startWith, switchMap, retry, tap } from 'rxjs/operators';

@Component({
  selector: 'page-package-details',
  templateUrl: 'package-details.component.html',
  styleUrls: ['package-details.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class PackageDetailsComponent {
  @ViewChild('handlungsAnweisung', { static: false, read: ElementRef }) handlungsAnweisung: ElementRef<HTMLDivElement>;

  get breadcrumbKey(): string {
    return this._config.get('process.ids.packageInspection');
  }

  packageId$ = this._activatedRoute.params.pipe(map((params) => String(params.id)));

  packageDetails$: Observable<PackageDetailResponseDTO> = this.packageId$.pipe(
    switchMap((id) => this._packageInspectionService.getPackageDetails(id).pipe(retry(3))),
    tap((details) => {
      this.createBreadcrumbIfNotExists(details);
    }),
    shareReplay(1),
  );

  childActionsSubject = new Subject<NestedKeyValueDTOOfStringAndString[]>();

  childActions$ = this.childActionsSubject.asObservable().pipe(startWith(undefined));

  packageActions$: Observable<NestedKeyValueDTOOfStringAndString[]> = this.packageDetails$.pipe(
    map((details) => details.actions),
  );

  displayActions$ = this.packageActions$.pipe(
    switchMap((actions) => this.childActions$.pipe(map((childActions) => childActions ?? actions))),
  );

  detailsListHeight: number;

  constructor(
    private _activatedRoute: ActivatedRoute,
    private _packageInspectionService: DomainPackageInspectionService,
    private _config: Config,
    private _breadcrumb: BreadcrumbService,
    private _router: Router,
    private _toast: ToasterService,
    private _uiModal: UiModalService,
    private _cdr: ChangeDetectorRef,
  ) {}

  private _getListPageBreadcrumb(): Promise<Breadcrumb> {
    return this._breadcrumb
      .getBreadcrumbsByKeyAndTags$(this.breadcrumbKey, ['filter'])
      .pipe(
        first(),
        map((b) => b[0]),
      )
      .toPromise();
  }

  async onActionClick(action: NestedKeyValueDTOOfStringAndString) {
    if (action.command === 'NEXT') {
      this.onNextAction(action);
    } else {
      try {
        const changes = await this.changePackageStatus(action.value);
        this.updatedToaster();
        this.navigateToList(changes);
      } catch (error) {
        this._uiModal.error('Fehler beim Speichern der Daten.', error);
      }
    }
    this.calculateListHeight();
  }

  async navigateToList({
    previousArrivalStatus,
    newArrivalStatus,
  }: {
    previousArrivalStatus: ArrivalStatus;
    newArrivalStatus: ArrivalStatus;
  }) {
    // Navigiere nur zurück, wenn der Status nicht 4 oder 16 ist (Fehlt)
    if ([4, 16].includes(previousArrivalStatus)) {
      this._router.navigate([`/filiale/package-inspection/packages`]);
      return;
    }

    const breadcrumb = await this._getListPageBreadcrumb();

    if (breadcrumb) {
      const packageId = await this.packageId$.pipe(first()).toPromise();
      this._router.navigate([breadcrumb.path], {
        queryParams: {
          ...breadcrumb.params,
          updated_packageId: packageId,
          updated_arrivalStatus: newArrivalStatus,
        },
      });
    } else {
      this._router.navigate([`/filiale/package-inspection/packages`]);
    }
  }

  updatedToaster() {
    this._toast.open({
      message: 'Ihre Eingabe wurde gespeichert.',
    });
  }

  async onNextAction(action: NestedKeyValueDTOOfStringAndString) {
    this.childActionsSubject.next(action.children || undefined);
  }

  async changePackageStatus(status: string): Promise<{
    previousArrivalStatus: ArrivalStatus;
    newArrivalStatus: ArrivalStatus;
  }> {
    const packageDetails = await this.packageDetails$.pipe(first()).toPromise();
    await this._packageInspectionService.changePackageStatus(packageDetails.package, status).toPromise();

    return {
      previousArrivalStatus: packageDetails.package.arrivalStatus,
      newArrivalStatus: +status as ArrivalStatus,
    };
  }

  async createBreadcrumbIfNotExists(details: PackageDetailResponseDTO): Promise<void> {
    const crumb: Breadcrumb = {
      key: this.breadcrumbKey,
      name: details.package.packageNumber,
      path: `/filiale/package-inspection/packages/${details.package.id}`,
      section: 'branch',
      tags: ['details'],
    };

    await this._breadcrumb.addBreadcrumbIfNotExists(crumb);
  }

  @HostListener('window:resize')
  calculateListHeight() {
    const handlungsAnweisungHeight = this.handlungsAnweisung?.nativeElement?.offsetHeight ?? 0;
    const windowHeight = window.innerHeight;
    this.detailsListHeight = windowHeight - handlungsAnweisungHeight - 516;
    this._cdr.markForCheck();
  }
}
