import {
  Component,
  ChangeDetectionStrategy,
  OnInit,
  ViewChild,
  ElementRef,
} from '@angular/core';
import { Router } from '@angular/router';
import { ApplicationProcess, ApplicationService } from '@core/application';
import { BreadcrumbService } from '@core/breadcrumb';
import { DomainCheckoutService } from '@domain/checkout';
import { injectOpenMessageModal } from '@modal/message';
import {
  CustomerOrdersNavigationService,
  ProductCatalogNavigationService,
} from '@shared/services/navigation';
import { NEVER, Observable, of } from 'rxjs';
import { delay, first, map, switchMap } from 'rxjs/operators';

@Component({
  selector: 'shell-process-bar',
  templateUrl: 'process-bar.component.html',
  styleUrls: ['process-bar.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class ShellProcessBarComponent implements OnInit {
  @ViewChild('processContainer')
  processContainer: ElementRef;

  section$: Observable<'customer' | 'branch'> = NEVER;

  processes$: Observable<ApplicationProcess[]> = NEVER;

  showStartProcessText$: Observable<boolean> = NEVER;

  hovered: boolean;
  showScrollArrows: boolean;
  showArrowLeft: boolean;
  showArrowRight: boolean;

  trackByFn = (_: number, process: ApplicationProcess) => process.id;

  openMessageModal = injectOpenMessageModal();

  constructor(
    private _app: ApplicationService,
    private _router: Router,
    private _catalogNavigationService: ProductCatalogNavigationService,
    private _customerOrderNavigationService: CustomerOrdersNavigationService,
    private _checkoutService: DomainCheckoutService,
    private _breadcrumb: BreadcrumbService,
  ) {}

  ngOnInit() {
    this.initSection$();
    this.initProcesses$();
    this.initShowStartProcessText$();
    this.checkScrollArrowVisibility();
  }

  initSection$() {
    this.section$ = of(undefined);
  }

  initProcesses$() {
    // TODO: Use implementation from develop
    this.processes$ = this.section$.pipe(
      switchMap((section) => this._app.getProcesses$(section)),
      // TODO: Nach Prämie release kann der Filter rausgenommen werden
      map((processes) =>
        processes.filter(
          (process) =>
            process.type === 'cart' || process.type === 'cart-checkout',
        ),
      ),
    );
  }

  initShowStartProcessText$() {
    this.showStartProcessText$ = this.processes$.pipe(
      map((processes) => processes.length === 0),
    );
  }

  async createProcess(target = 'product') {
    // const process = await this.createCartProcess();
    this.navigateTo(target, Date.now());

    setTimeout(() => this.scrollToEnd(), 25);
  }

  static REGEX_PROCESS_NAME = /^Vorgang \d+$/;

  async createCartProcess() {
    return this._app.createCustomerProcess();
  }

  async navigateTo(target: string, processId: number) {
    switch (target) {
      case 'product':
        await this._catalogNavigationService
          .getArticleSearchBasePath(processId)
          .navigate();
        break;
      case 'customer':
        await this._router.navigate([
          '/kunde',
          processId,
          'customer',
          'search',
        ]);
        break;
      case 'goods-out':
        await this._router.navigate(['/kunde', processId, 'goods', 'out']);
        break;
      case 'order':
        await this._customerOrderNavigationService
          .getCustomerOrdersBasePath(processId)
          .navigate();
        break;

      default:
        await this._router.navigate(['/kunde', processId, target]);
        break;
    }
  }

  async closeAllProcesses() {
    const processes = await this.processes$.pipe(first()).toPromise();
    this.openMessageModal({
      title: 'Vorgänge schließen',
      message: `Sind Sie sich sicher, dass sie alle ${processes.length} Vorgänge schließen wollen?`,
      actions: [
        { label: 'Abbrechen', value: false },
        {
          label: 'leere Warenkörbe',
          value: true,
          action: () => this.handleCloseEmptyCartProcesses(),
        },
        {
          label: 'Ja, alle',
          value: true,
          primary: true,
          action: () => this.handleCloseAllProcesses(),
        },
      ],
    });
    this.checkScrollArrowVisibility();
  }

  async handleCloseEmptyCartProcesses() {
    let processes = await this.processes$.pipe(first()).toPromise();
    for (const process of processes) {
      const cart = await this._checkoutService
        .getShoppingCart({ processId: process.id })
        .pipe(first())
        .toPromise();

      if (cart?.items?.length === 0 || cart?.items === undefined) {
        this._app.removeProcess(process?.id);
      }

      processes = await this.processes$.pipe(delay(1), first()).toPromise();

      this._router.navigate(['/kunde', 'dashboard']);
    }
  }

  async handleCloseAllProcesses() {
    const processes = await this.processes$.pipe(first()).toPromise();
    processes.forEach((process) => this._app.removeProcess(process?.id));
    this._router.navigate(['/kunde', 'dashboard']);
  }

  onMouseWheel(event: any) {
    // Ermöglicht es, am Desktop die Prozessleiste mit dem Mausrad hoch/runter horizontal zu scrollen
    if (event.deltaY > 0) {
      this.processContainer.nativeElement.scrollLeft += 100;
    } else {
      this.processContainer.nativeElement.scrollLeft -= 100;
    }
    event.preventDefault();
  }

  scrollLeft() {
    this.processContainer.nativeElement.scrollLeft -= 100;
  }

  scrollRight() {
    this.processContainer.nativeElement.scrollLeft += 100;
  }

  scrollToEnd() {
    this.processContainer.nativeElement.scrollLeft =
      this.processContainer?.nativeElement?.scrollWidth +
      this.processContainer?.nativeElement?.scrollLeft;
  }

  checkScrollArrowVisibility() {
    this.showScrollArrows =
      this.processContainer?.nativeElement?.scrollWidth > 0;
    this.showArrowRight =
      ((this.processContainer?.nativeElement?.scrollWidth -
        this.processContainer?.nativeElement?.scrollLeft) |
        0) <=
      this.processContainer?.nativeElement?.offsetWidth;
    this.showArrowLeft = this.processContainer?.nativeElement?.scrollLeft <= 0;
  }
}
