import {
  Component,
  ChangeDetectionStrategy,
  OnInit,
  OnDestroy,
  inject,
  effect,
  untracked,
} from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import {
  BehaviorSubject,
  Subject,
  Subscription,
  firstValueFrom,
  fromEvent,
} from 'rxjs';
import { CustomerSearchStore } from './store/customer-search.store';
import { provideComponentStore } from '@ngrx/component-store';
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { delay, filter, first, switchMap, takeUntil } from 'rxjs/operators';
import {
  CustomerCreateNavigation,
  CustomerSearchNavigation,
} from '@shared/services/navigation';
import { CustomerSearchMainAutocompleteProvider } from './providers/customer-search-main-autocomplete.provider';
import { FilterAutocompleteProvider } from '@shared/components/filter';
import { toSignal } from '@angular/core/rxjs-interop';
import { provideCancelSearchSubject } from '@shared/services/cancel-subject';
import { injectFeedbackErrorDialog } from '@isa/ui/dialog';

@Component({
  selector: 'page-customer-search',
  templateUrl: 'customer-search.component.html',
  styleUrls: ['customer-search.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    provideComponentStore(CustomerSearchStore),
    provideCancelSearchSubject(),
    {
      provide: FilterAutocompleteProvider,
      useClass: CustomerSearchMainAutocompleteProvider,
      multi: true,
    },
  ],
  standalone: false,
})
export class CustomerSearchComponent implements OnInit, OnDestroy {
  #errorFeedbackDialog = injectFeedbackErrorDialog();
  private _store = inject(CustomerSearchStore);
  private _activatedRoute = inject(ActivatedRoute);
  private _router = inject(Router);
  private _breadcrumbService = inject(BreadcrumbService);
  private _navigation = inject(CustomerSearchNavigation);
  private _createNavigation = inject(CustomerCreateNavigation);

  private searchStore = inject(CustomerSearchStore);

  keyEscPressed = toSignal(
    fromEvent(document, 'keydown').pipe(
      filter((e: KeyboardEvent) => e.key === 'Escape'),
    ),
  );

  get breadcrumb() {
    let breadcrumb: string;

    breadcrumb = this.snapshot.data?.breadcrumb;

    if (!breadcrumb) {
      breadcrumb = this.firstChildSnapshot?.data?.breadcrumb;
    }

    return breadcrumb;
  }

  private _breadcrumbs$ = this._store.processId$.pipe(
    filter((id) => !!id),
    switchMap((id) =>
      this._breadcrumbService.getBreadcrumbsByKeyAndTag$(id, 'customer'),
    ),
  );

  side$ = new BehaviorSubject<string | undefined>(undefined);

  get side() {
    return this.side$.value;
  }

  get snapshot() {
    return this._activatedRoute.snapshot;
  }

  get parentSnapshot() {
    return this._activatedRoute.parent?.snapshot;
  }

  get firstChildSnapshot() {
    return this._activatedRoute.firstChild?.snapshot;
  }

  readonly processId$ = this._store.processId$;

  private _eventsSubscription: Subscription;

  private _customerChangedSubscription: Subscription;

  private _onDestroy$ = new Subject<void>();

  constructor() {}

  ngOnInit(): void {
    this.checkAndUpdateProcessId();
    this.checkAndUpdateSide();
    this.checkAndUpdateCustomerId();
    this.checkBreadcrumbs();

    // Wenn der delay nicht angewendet wird, dann wird die Breacrumb zwei mal angelegt
    this._customerChangedSubscription = this._store.customer$
      .pipe(takeUntil(this._onDestroy$), delay(1))
      .subscribe((c) => {
        this.checkDetailsBreadcrumb();
      });

    this._eventsSubscription = this._router.events
      .pipe(takeUntil(this._onDestroy$))
      .subscribe((event) => {
        if (event instanceof NavigationEnd) {
          this.checkAndUpdateProcessId();
          this.checkAndUpdateSide();
          this.checkAndUpdateCustomerId();
          this.checkBreadcrumbs();
        }
      });

    this._store.customerListResponse$
      .pipe(takeUntil(this._onDestroy$))
      .subscribe(
        async ([response, filter, processId, restored, skipNavigation]) => {
          if (this._store.processId === processId) {
            if (skipNavigation) {
              return;
            }

            if (response.hits === 1) {
              // Navigate to details page
              const customer = response.result[0];

              if (customer.id < 0) {
                // #5375 - Zusätzlich soll bei Kunden bei denen ein Upgrade möglich ist ein Dialog angezeigt werden, dass Kundenneuanlage mit Kundenkarte nicht möglich ist
                await firstValueFrom(
                  this.#errorFeedbackDialog({
                    data: {
                      errorMessage:
                        'Kundenneuanlage mit Kundenkarte nicht möglich',
                    },
                  }).closed,
                );
                // navigate to create customer
                // const route = this._createNavigation.upgradeCustomerRoute({ processId, customerInfo: customer });
                // await this._router.navigate(route.path, { queryParams: route.queryParams });
                return;
              } else {
                const route = this._navigation.detailsRoute({
                  processId,
                  customerId: customer.id,
                });
                await this._router.navigate(route.path, {
                  queryParams: filter.getQueryParams(),
                });
              }
            } else if (response.hits > 1) {
              const route = this._navigation.listRoute({ processId, filter });

              if (
                (['details'].includes(this.breadcrumb) &&
                  response?.result?.some(
                    (c) => c.id === this._store.customerId,
                  )) ||
                restored
              ) {
                await this._router.navigate([], {
                  queryParams: route.queryParams,
                });
              } else {
                await this._router.navigate(route.path, {
                  queryParams: route.queryParams,
                });
              }
            }

            this.checkBreadcrumbs();
          }
        },
      );
  }

  ngOnDestroy(): void {
    this._eventsSubscription.unsubscribe();
    this._customerChangedSubscription.unsubscribe();
    this.side$.complete();
    this._onDestroy$.next();
    this._onDestroy$.complete();
    this._store.ngOnDestroy();
  }

  checkAndUpdateProcessId() {
    let processId: number;

    processId = this.snapshot.data?.processId;
    if (!processId) {
      processId = this.parentSnapshot?.data?.processId;
    }

    processId = +processId;

    if (processId !== this._store.processId) {
      this._store.setProcessId(processId);
      this._store.reset(this._activatedRoute.snapshot.queryParams);
      if (!['main', 'filter'].some((s) => s === this.breadcrumb)) {
        const skipNavigation = [
          'orders',
          'order-details',
          'order-details-history',
        ].includes(this.breadcrumb);
        this._store.search({ skipNavigation });
      }
    }
  }

  checkAndUpdateSide() {
    let side: string;

    side = this.snapshot.data?.side;

    if (!side) {
      side = this.firstChildSnapshot?.data?.side;
    }

    if (side !== this.side) {
      this.side$.next(side);
    }
  }

  checkAndUpdateCustomerId() {
    let customerId: number;

    customerId = this.snapshot.params.customerId;

    if (!customerId) {
      customerId = this.firstChildSnapshot?.params.customerId;
    }

    if (customerId !== this._store.customer?.id) {
      this._store.selectCustomer({ customerId });
    }
  }

  async checkBreadcrumbs(force = false) {
    await this.checkCreateCustomerBreadcrumb();
    await this.checkMainBreadcrumb();
    await this.checkSearchBreadcrumb();
    await this.checkDetailsBreadcrumb();
    await this.checkHistoryBreadcrumb();
    await this.checkEditBreadcrumb();
    await this.checkKundenkarteBreadcrumb();
    await this.checkOrdersBreadcrumb();
    await this.checkOrderDetailsBreadcrumb();
    await this.checkOrderDetailsHistoryBreadcrumb();
  }

  getBreadcrumbs(): Promise<Breadcrumb[]> {
    return this._breadcrumbs$.pipe(first()).toPromise();
  }

  async getMainBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('main'));
  }

  async checkMainBreadcrumb() {
    const mainBreadcrumb = await this.getMainBreadcrumb();

    if (!mainBreadcrumb) {
      const navigation = this._navigation.defaultRoute({
        processId: this._store.processId,
      });
      const breadcrumb: Breadcrumb = {
        key: this._store.processId,
        tags: ['customer', 'search', 'main'],
        name: 'Kundensuche',
        path: navigation.path,
        params: { ...this._store.queryParams, ...navigation.queryParams },
        section: 'customer',
      };

      this._breadcrumbService.addBreadcrumb(breadcrumb);
    } else {
      this._breadcrumbService.patchBreadcrumb(mainBreadcrumb.id, {
        params: {
          ...this.snapshot.queryParams,
          ...(mainBreadcrumb.params ?? {}),
        },
      });
    }
  }

  async getCreateCustomerBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find(
      (b) => b.tags.includes('create') && b.tags.includes('customer'),
    );
  }

  async checkCreateCustomerBreadcrumb() {
    const createCustomerBreadcrumb = await this.getCreateCustomerBreadcrumb();

    if (createCustomerBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(createCustomerBreadcrumb.id);
    }
  }

  async getSearchBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find(
      (b) => b.tags.includes('list') && b.tags.includes('search'),
    );
  }

  async checkSearchBreadcrumb() {
    const searchBreadcrumb = await this.getSearchBreadcrumb();

    if (
      [
        'search',
        'details',
        'history',
        'edit',
        'history',
        'orders',
        'order-details',
        'add-billing-address',
        'edit-billing-address',
        'add-shipping-address',
        'edit-shipping-address',
        'filter',
        'kundenkarte',
      ].includes(this.breadcrumb)
    ) {
      const name = this._store.queryParams?.main_qs || 'Suche';

      if (!searchBreadcrumb) {
        const navigation = this._navigation.listRoute({
          processId: this._store.processId,
        });
        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'list'],
          name,
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      } else {
        this._breadcrumbService.patchBreadcrumb(searchBreadcrumb.id, {
          params: this.snapshot.queryParams,
          name,
        });
      }
    } else {
      if (searchBreadcrumb) {
        this._breadcrumbService.removeBreadcrumb(searchBreadcrumb.id);
      }
    }
  }

  async getDetailsBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find(
      (b) => b.tags.includes('details') && b.tags.includes('search'),
    );
  }

  async checkDetailsBreadcrumb() {
    const detailsBreadcrumb = await this.getDetailsBreadcrumb();

    if (
      [
        'details',
        'history',
        'edit',
        'history',
        'orders',
        'order-details',
        'add-billing-address',
        'edit-billing-address',
        'add-shipping-address',
        'edit-shipping-address',
        'kundenkarte',
      ].includes(this.breadcrumb)
    ) {
      const customer = this._store.customer;
      const fullName =
        `${customer?.firstName ?? ''} ${customer?.lastName ?? ''}`.trim();

      if (!detailsBreadcrumb) {
        const navigation = this._navigation.detailsRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'details', 'search'],
          name: fullName || 'Kunde',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      } else if (fullName) {
        const navigation = this._navigation.detailsRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
        });

        this._breadcrumbService.patchBreadcrumb(detailsBreadcrumb.id, {
          name: fullName,
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
        });
      }
    } else if (detailsBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(detailsBreadcrumb.id);
    }
  }

  async getHistoryBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('history'));
  }

  async checkHistoryBreadcrumb() {
    const historyBreadcrumb = await this.getHistoryBreadcrumb();

    if (this.breadcrumb === 'history') {
      if (!historyBreadcrumb) {
        const navigation = this._navigation.historyRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'history'],
          name: 'Historie',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      } else {
        const navigation = this._navigation.historyRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
        });

        this._breadcrumbService.patchBreadcrumb(historyBreadcrumb.id, {
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
        });
      }
    } else if (historyBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(historyBreadcrumb.id);
    }
  }

  async getEditBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('edit'));
  }

  async checkEditBreadcrumb() {
    const editBreadcrumb = await this.getEditBreadcrumb();

    if (this.breadcrumb === 'edit') {
      if (!editBreadcrumb) {
        const navigation = this._navigation.editRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
          isB2b: this._store.isBusinessKonto,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'edit'],
          name: 'Bearbeiten',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      }
    } else if (editBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(editBreadcrumb.id);
    }
  }

  async getKundenkarteBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('kundenkarte'));
  }

  async checkKundenkarteBreadcrumb() {
    const kundenkarteBreadcrumb = await this.getKundenkarteBreadcrumb();

    if (this.breadcrumb === 'kundenkarte') {
      if (!kundenkarteBreadcrumb) {
        const navigation = this._navigation.kundenkarteRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'kundenkarte'],
          name: 'Kundenkarte',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      }
    } else if (kundenkarteBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(kundenkarteBreadcrumb.id);
    }
  }

  async getOrdersBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('orders'));
  }

  async checkOrdersBreadcrumb() {
    const ordersBreadcrumb = await this.getOrdersBreadcrumb();

    if (
      this.breadcrumb === 'orders' ||
      this.breadcrumb === 'order-details' ||
      this.breadcrumb === 'order-details-history'
    ) {
      if (!ordersBreadcrumb) {
        const navigation = this._navigation.ordersRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'orders'],
          name: 'Bestellungen',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      }
    } else if (ordersBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(ordersBreadcrumb.id);
    }
  }

  async getOrderDetailsBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('order-details'));
  }

  async checkOrderDetailsBreadcrumb() {
    const orderDetailsBreadcrumb = await this.getOrderDetailsBreadcrumb();

    if (
      this.breadcrumb === 'order-details' ||
      this.breadcrumb === 'order-details-history'
    ) {
      if (!orderDetailsBreadcrumb) {
        const navigation = this._navigation.orderDetialsRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
          orderId: this._store.order?.id,
          orderItemId: this._store.selectedOrderItemId,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'order-details'],
          name: 'Details',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      }
    } else if (orderDetailsBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(orderDetailsBreadcrumb.id);
    }
  }

  async getOrderDetailsHistoryBreadcrumb(): Promise<Breadcrumb | undefined> {
    const breadcrumbs = await this.getBreadcrumbs();
    return breadcrumbs.find((b) => b.tags.includes('order-details-history'));
  }

  async checkOrderDetailsHistoryBreadcrumb() {
    const orderDetailsHistoryBreadcrumb =
      await this.getOrderDetailsHistoryBreadcrumb();

    if (this.breadcrumb === 'order-details-history') {
      if (!orderDetailsHistoryBreadcrumb) {
        const navigation = this._navigation.orderDetailsHistoryRoute({
          processId: this._store.processId,
          customerId: this._store.customerId,
          orderId: this._store.order?.id,
          orderItemId: this._store.selectedOrderItemId,
        });

        const breadcrumb: Breadcrumb = {
          key: this._store.processId,
          tags: ['customer', 'search', 'order-details-history'],
          name: 'Historie',
          path: navigation.path,
          params: { ...this._store.queryParams, ...navigation.queryParams },
          section: 'customer',
        };

        this._breadcrumbService.addBreadcrumb(breadcrumb);
      }
    } else if (orderDetailsHistoryBreadcrumb) {
      this._breadcrumbService.removeBreadcrumb(
        orderDetailsHistoryBreadcrumb.id,
      );
    }
  }

  cancelSearchEffect = effect(() => {
    this.keyEscPressed();
    untracked(() => {
      this.searchStore.cancelSearch();
    });
  });
}
