import {
  AfterViewInit,
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  OnDestroy,
  OnInit,
  Renderer2,
  ViewChild,
} from '@angular/core';
import { ApplicationService } from '@core/application';
import { AuthService } from '@core/auth';
import { EnvironmentService } from '@core/environment';
import { BranchSelectorComponent } from '@shared/components/branch-selector';
import { BreadcrumbComponent } from '@shared/components/breadcrumb';
import { BranchDTO } from '@generated/swagger/checkout-api';
import { UiOverlayTriggerDirective } from '@ui/common';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { combineLatest, fromEvent, Observable, Subject } from 'rxjs';
import { first, map, switchMap, takeUntil, withLatestFrom } from 'rxjs/operators';
import { ActionsSubject } from '@ngrx/store';
import { DomainAvailabilityService } from '@domain/availability';
import { provideComponentStore } from '@ngrx/component-store';
import { ArticleSearchService } from './article-search/article-search.store';
import { provideCancelSearchSubject } from '@shared/services/cancel-subject';

@Component({
  selector: 'page-catalog',
  templateUrl: 'page-catalog.component.html',
  styleUrls: ['page-catalog.component.scss'],
  providers: [provideComponentStore(ArticleSearchService), provideCancelSearchSubject()],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class PageCatalogComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild(BreadcrumbComponent, { read: ElementRef }) breadcrumbRef: ElementRef<HTMLElement>;
  @ViewChild(BranchSelectorComponent, { read: ElementRef }) branchSelectorRef: ElementRef<HTMLElement>;
  activatedProcessId$: Observable<string>;
  selectedBranch$: Observable<BranchDTO>;

  @ViewChild(UiOverlayTriggerDirective) branchInputNoBranchSelectedTrigger: UiOverlayTriggerDirective;

  get branchSelectorWidth() {
    return `${this.breadcrumbRef?.nativeElement?.clientWidth}px`;
  }

  _onDestroy$ = new Subject<void>();

  get isTablet$() {
    return this._environmentService.matchTablet$;
  }

  get isDesktop$() {
    return this._environmentService.matchDesktopLarge$;
  }

  defaultBranch$ = this._availability.getDefaultBranch();

  stockTooltipText$: Observable<string>;

  stockTooltipDisabled$: Observable<boolean>;

  get stockTooltipDisabled() {
    return this.branchInputNoBranchSelectedTrigger?.opened ? false : true;
  }

  constructor(
    public application: ApplicationService,
    private _availability: DomainAvailabilityService,
    private _uiModal: UiModalService,
    public auth: AuthService,
    private _environmentService: EnvironmentService,
    private _renderer: Renderer2,
    private _actions: ActionsSubject,
  ) {}

  ngOnInit() {
    this.activatedProcessId$ = this.application.activatedProcessId$.pipe(map((processId) => String(processId)));

    this.selectedBranch$ = this.activatedProcessId$.pipe(
      switchMap((processId) => this.application.getSelectedBranch$(Number(processId))),
    );

    this.stockTooltipText$ = combineLatest([this.defaultBranch$, this.selectedBranch$]).pipe(
      map(([defaultBranch, selectedBranch]) => {
        if (defaultBranch?.branchType === 4 && !selectedBranch) {
          return 'Bitte wählen Sie eine Filiale aus, um den Bestand zu sehen.';
        } else if (defaultBranch?.branchType !== 4 && !selectedBranch) {
          return 'Bitte wählen Sie eine Filiale aus, um den Bestand einer anderen Filiale zu sehen';
        }
        return '';
      }),
    );
  }

  ngAfterViewInit(): void {
    this._actions
      .pipe(takeUntil(this._onDestroy$), withLatestFrom(this.stockTooltipText$))
      .subscribe(([action, text]) => {
        if (action.type === 'OPEN_TOOLTIP_NO_BRANCH_SELECTED' && !!text) {
          this.branchInputNoBranchSelectedTrigger.open();
        }
      });

    fromEvent(this.branchSelectorRef.nativeElement, 'focusin')
      .pipe(takeUntil(this._onDestroy$), withLatestFrom(this.isTablet$))
      .subscribe(([_, isTablet]) => {
        if (isTablet) {
          this._renderer.setStyle(this.branchSelectorRef?.nativeElement, 'width', this.branchSelectorWidth);
        }
      });

    fromEvent(this.branchSelectorRef.nativeElement, 'focusout')
      .pipe(takeUntil(this._onDestroy$))
      .subscribe((_) => {
        this._renderer.removeStyle(this.branchSelectorRef?.nativeElement, 'width');
      });
  }

  ngOnDestroy(): void {
    this._onDestroy$.next();
    this._onDestroy$.complete();
  }

  async patchProcessData(selectedBranch: BranchDTO) {
    try {
      const processId = await this.activatedProcessId$.pipe(first()).toPromise();
      this.application.patchProcessData(Number(processId), { selectedBranch });
    } catch (error) {
      this._uiModal.open({
        title: 'Fehler beim aktualisieren der Daten des Prozesses',
        content: UiErrorModalComponent,
        data: error,
        config: { showScrollbarY: false },
      });
    }
  }
}
