import {
  Component,
  ChangeDetectionStrategy,
  OnDestroy,
  OnInit,
  OnChanges,
  SimpleChanges,
  EventEmitter,
  Output,
  ElementRef,
  inject,
  computed,
  input,
  effect,
  untracked,
} from '@angular/core';
import { Router } from '@angular/router';
import { ApplicationProcess, ApplicationService } from '@core/application';
import { Breadcrumb } from '@core/breadcrumb';
import { DomainCheckoutService } from '@domain/checkout';
import { CheckoutNavigationService } from '@shared/services/navigation';
import {
  BehaviorSubject,
  NEVER,
  Observable,
  combineLatest,
  isObservable,
} from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { TabService } from '@isa/core/tabs';
import {
  CheckoutMetadataService,
  ShoppingCartResource,
} from '@isa/checkout/data-access';

@Component({
  selector: 'shell-process-bar-item',
  templateUrl: 'process-bar-item.component.html',
  styleUrls: ['process-bar-item.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
  providers: [ShoppingCartResource],
})
export class ShellProcessBarItemComponent
  implements OnInit, OnDestroy, OnChanges
{
  #tabService = inject(TabService);
  #checkoutMetadataService = inject(CheckoutMetadataService);
  #shoppingCartResource = inject(ShoppingCartResource);

  tab = computed(() => this.#tabService.entityMap()[this.process().id]);

  shoppingCartId = computed(() => {
    return this.#checkoutMetadataService.getShoppingCartId(this.process().id);
  });

  shoppingCartIdEffect = effect(() => {
    const shoppingCartId = this.shoppingCartId();
    untracked(() =>
      this.#shoppingCartResource.setShoppingCartId(shoppingCartId),
    );
  });

  itemCount = computed(() => {
    const shoppingCart = this.#shoppingCartResource.resource.value();
    return shoppingCart?.items?.length ?? 0;
  });

  private _process$ = new BehaviorSubject<ApplicationProcess>(undefined);

  process$ = this._process$.asObservable();

  process = input.required<ApplicationProcess>();

  @Output()
  closed = new EventEmitter();

  showCart = computed(() => {
    return true;
  });

  currentLocationUrlTree = computed(() => {
    const tab = this.tab();
    const current = tab.location.locations[tab.location.current];

    if (current?.url) {
      return this._router.parseUrl(current.url);
    }

    return null;
  });

  navigateByUrl(event: MouseEvent) {
    event?.preventDefault();
    this._router.navigateByUrl(this.currentLocationUrlTree());
  }

  activatedProcessId$ = this._app.activatedProcessId$;

  latestBreadcrumb$: Observable<Breadcrumb> = NEVER;

  routerLink$: Observable<string[] | unknown[]> = NEVER;

  queryParams$: Observable<object> = NEVER;

  isActive$: Observable<boolean> = NEVER;

  showCloseButton$: Observable<boolean> = NEVER;

  cartItemCount$: Observable<number> = NEVER;

  constructor(
    private _app: ApplicationService,
    private _router: Router,
    private _checkout: DomainCheckoutService,
    private _checkoutNavigationService: CheckoutNavigationService,
    public _elRef: ElementRef<HTMLElement>,
  ) {}

  ngOnChanges({ process }: SimpleChanges): void {
    if (process) {
      this._process$.next(process.currentValue);
    }
  }

  ngOnInit() {
    this.initRouterLink$();
    this.initQueryParams$();
    this.initIsActive$();
    this.initShowCloseButton$();
  }

  scrollIntoView() {
    setTimeout(
      () =>
        this._elRef.nativeElement.scrollIntoView({
          behavior: 'smooth',
          block: 'center',
        }),
      0,
    );
  }

  getCheckoutPath(processId: number) {
    return this._checkoutNavigationService.getCheckoutReviewPath(processId)
      .path;
  }

  initRouterLink$() {
    this.routerLink$ = this.latestBreadcrumb$.pipe(
      map((breadcrumb) =>
        breadcrumb?.path instanceof Array
          ? breadcrumb.path
          : [breadcrumb?.path],
      ),
    );
  }

  initQueryParams$() {
    this.queryParams$ = this.latestBreadcrumb$.pipe(
      map((breadcrumb) => breadcrumb?.params),
    );
  }

  initIsActive$() {
    if (isObservable(this.activatedProcessId$) && isObservable(this.process$)) {
      this.isActive$ = combineLatest([
        this.activatedProcessId$,
        this.process$,
      ]).pipe(
        map(([activatedId, process]) => process?.id === activatedId),
        tap((isActive) => {
          if (isActive) {
            this.scrollIntoView();
          }
        }),
      );
    }
  }

  initShowCloseButton$() {
    if (isObservable(this.isActive$) && isObservable(this.process$)) {
      this.showCloseButton$ = this.process$.pipe(
        map((process) => process?.closeable),
      );
    }
  }

  ngOnDestroy() {
    this._process$.complete();
  }

  async close() {
    await this.navigate();
    this._app.removeProcess(this.process().id);
    this.closed.emit();
  }

  async navigate(breadcrumb?: Breadcrumb) {
    if (breadcrumb) {
      if (breadcrumb.path instanceof Array) {
        await this._router.navigate(breadcrumb.path, {
          queryParams: breadcrumb.params,
        });
      } else {
        await this._router.navigate([breadcrumb.path], {
          queryParams: breadcrumb.params,
        });
      }
    } else {
      await this._router.navigate(['/kunde/dashboard']);
    }
  }
}
