import {
  AsyncPipe,
  DatePipe,
  NgFor,
  NgIf,
  NgSwitch,
  NgSwitchCase,
  NgTemplateOutlet,
} from '@angular/common';
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Input,
  Output,
  inject,
} from '@angular/core';
import {
  DBHOrderItemListItemDTO,
  KeyValueDTOOfStringAndString,
  NotificationChannel,
  OrderDTO,
} from '@generated/swagger/oms-api';
import { PickupShelfDetailsStore } from '../../store';
import { map, shareReplay, tap, withLatestFrom } from 'rxjs/operators';
import { BehaviorSubject, Observable, combineLatest } from 'rxjs';
import { DateAdapter, UiCommonModule } from '@ui/common';
import { IconModule } from '@shared/components/icon';
import { UiDropdownModule } from '@ui/dropdown';
import { UiSpinnerModule } from '@ui/spinner';
import { PickupShelfNotificationsChannelPipe } from '../pipes/notifications-channel.pipe';
import { PickupShelfProcessingStatusPipe } from '../pipes/processing-status.pipe';
import { UiDatepickerModule } from '@ui/datepicker';
import { PickUpShelfDetailsHeaderNavMenuComponent } from '../pickup-shelf-details-header-nav-menu/pickup-shelf-details-header-nav-menu.component';
import { SkeletonLoaderComponent } from '@shared/components/loader';
import { toSignal } from '@angular/core/rxjs-interop';
import { MatomoModule } from 'ngx-matomo-client';
import { getEnabledCustomerFeature } from '@isa/crm/data-access';

@Component({
  selector: 'page-pickup-shelf-details-header',
  templateUrl: 'pickup-shelf-details-header.component.html',
  styleUrls: ['pickup-shelf-details-header.component.scss'],
  host: { class: 'page-pickup-shelf-details-header' },
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    NgIf,
    NgFor,
    AsyncPipe,
    IconModule,
    NgTemplateOutlet,
    NgSwitch,
    NgSwitchCase,
    DatePipe,
    UiDropdownModule,
    UiSpinnerModule,
    PickupShelfNotificationsChannelPipe,
    PickupShelfProcessingStatusPipe,
    UiCommonModule,
    UiDatepickerModule,
    PickUpShelfDetailsHeaderNavMenuComponent,
    SkeletonLoaderComponent,
    MatomoModule,
  ],
})
export class PickUpShelfDetailsHeaderComponent {
  private _store = inject(PickupShelfDetailsStore);

  @Output()
  editClick = new EventEmitter<DBHOrderItemListItemDTO>();

  @Output()
  handleAction = new EventEmitter<KeyValueDTOOfStringAndString>();

  @Output()
  updateDate = new EventEmitter<{
    date: Date;
    type?: 'delivery' | 'pickup' | 'preferred';
  }>();

  orderItemSubsetLoading$ = this._store.orderItemSubsetLoading$;

  fetchingOrder$ = this._store.fetchingOrder$;

  order$ = this._store.order$;

  order = toSignal(this.order$);

  findLatestPreferredPickUpDate$: Observable<Date> = this.order$.pipe(
    withLatestFrom(this._store.selectedOrderItemIds$),
    map(([order, selectedOrderItemIds]) => {
      let latestDate;
      const subsetItems = order?.items
        ?.reduce((acc, item) => {
          return [...acc, ...item.data.subsetItems];
        }, [])
        ?.filter(
          (a) =>
            !!a.data.preferredPickUpDate &&
            selectedOrderItemIds.find((id) => id === a.data.id),
        );

      if (subsetItems?.length > 0) {
        latestDate = new Date(
          subsetItems?.reduce((a, b) => {
            return new Date(a.data.preferredPickUpDate) >
              new Date(b.data.preferredPickUpDate)
              ? a
              : b;
          })?.data?.preferredPickUpDate,
        );
      }

      return latestDate;
    }),
  );

  notificationsChannel$: Observable<NotificationChannel> = this.order$.pipe(
    map((order) => order?.notificationChannels ?? 0),
  );

  @Input()
  processId?: number;

  get isKulturpass() {
    return this.order()?.features?.orderSource === 'KulturPass';
  }

  minDateDatepicker = this.dateAdapter.addCalendarDays(
    this.dateAdapter.today(),
    -1,
  );
  today = this.dateAdapter.today();

  // Daten die im Header Angezeigt werden sollen
  orderItem$ = combineLatest([
    this._store.selectedOrderItem$, // Wenn man im Abholfach ist muss das ausgewählte OrderItem genommen werden
    this._store.selectedOrderItems$.pipe(
      map((orderItems) => orderItems?.find((_) => true)),
    ), // Wenn man in der Warenausgabe ist muss man das erste OrderItem nehmen
  ]).pipe(
    map(
      ([selectedOrderItem, selectedOrderItems]) =>
        selectedOrderItem || selectedOrderItems,
    ),
  );

  changeDateLoader$ = new BehaviorSubject<boolean>(false);
  changePreferredDateLoader$ = new BehaviorSubject<boolean>(false);
  changeStatusLoader$ = new BehaviorSubject<boolean>(false);
  changeStatusDisabled$ = this._store.disableHeaderStatusDropdown$;

  changeDateDisabled$ = this.changeStatusDisabled$;

  fetchingCustomerDone$ = this._store.fetchingCustomer$.pipe(
    map((fetchingCustomer) => !fetchingCustomer),
  );

  customer$ = this._store.customer$;

  customerFeature$ = this.customer$.pipe(
    map((customer) => getEnabledCustomerFeature(customer?.features)),
    shareReplay(),
  );

  statusActions$ = this.orderItem$.pipe(
    map((orderItem) =>
      orderItem?.actions?.filter((action) => action.enabled === false),
    ),
  );

  crudaUpdate$ = this.orderItem$.pipe(
    map((orederItem) => !!(orederItem?.cruda & 4)),
  );

  editButtonDisabled$ = combineLatest([
    this.changeStatusLoader$,
    this.crudaUpdate$,
  ]).pipe(
    map(
      ([changeStatusLoader, crudaUpdate]) => changeStatusLoader || !crudaUpdate,
    ),
  );

  canEditStatus$ = combineLatest([this.statusActions$, this.crudaUpdate$]).pipe(
    map(
      ([statusActions, crudaUpdate]) =>
        statusActions?.length > 0 && crudaUpdate,
    ),
  );

  constructor(
    private dateAdapter: DateAdapter,
    private cdr: ChangeDetectorRef,
  ) {}

  async handleActionClick(action?: KeyValueDTOOfStringAndString) {
    this.changeStatusLoader$.next(true);
    this.handleAction.emit(action);
    setTimeout(() => this.changeStatusLoader$.next(false), 1000);
    this.cdr.markForCheck();
  }

  updatePickupDeadline(date: Date) {
    this.updateDate.emit({ date, type: 'pickup' });
  }

  updateEstimatedShippingDate(date: Date) {
    this.updateDate.emit({ date, type: 'delivery' });
  }

  updatePreferredPickUpDate(date: Date) {
    this.updateDate.emit({ date, type: 'preferred' });
  }
}
