import { DatePipe } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output, HostBinding } from '@angular/core';
import { ApplicationService } from '@core/application';
import { EnvironmentService } from '@core/environment';
import { DomainAvailabilityService, DomainInStockService } from '@domain/availability';
import { ComponentStore } from '@ngrx/component-store';
import { ItemDTO } from '@generated/swagger/cat-search-api';
import { DateAdapter } from '@ui/common';
import { isEqual } from 'lodash';
import { combineLatest } from 'rxjs';
import { debounceTime, switchMap, map, filter, first } from 'rxjs/operators';
import { ArticleSearchService } from '../article-search.store';
import { ProductCatalogNavigationService } from '@shared/services/navigation';
import { Store } from '@ngrx/store';

export interface SearchResultItemComponentState {
  item?: ItemDTO;
  selected: boolean;
  selectable: boolean;
}

@Component({
  selector: 'search-result-item',
  templateUrl: 'search-result-item.component.html',
  styleUrls: ['search-result-item.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [DatePipe],
  standalone: false,
})
export class SearchResultItemComponent extends ComponentStore<SearchResultItemComponentState> {
  @Input()
  get item() {
    return this.get((s) => s.item);
  }
  set item(item: ItemDTO) {
    if (!isEqual(this.item, item)) {
      this.patchState({ item });
    }
  }

  readonly item$ = this.select((s) => s.item);

  @Input() selected: boolean = false;

  @Input()
  get selectable() {
    return this.get((s) => s.selectable);
  }
  set selectable(selectable: boolean) {
    if (this.selectable !== selectable) {
      this.patchState({ selectable });
    }
  }

  @Input()
  primaryOutletActive?: boolean = false;

  @Input() isActive: boolean;

  @Output()
  selectedChange = new EventEmitter<ItemDTO>();

  get contributors() {
    return this.item?.product?.contributors?.split(';').map((val) => val.trim());
  }

  get publicationDate() {
    if (this.item?.product?.publicationDate) {
      const date = this._dateAdapter.parseDate(this.item.product.publicationDate);

      if (this._dateAdapter.getDate(date) === 1 && this._dateAdapter.getMonth(date) === 0) {
        return this._datePipe.transform(date, 'y');
      }

      return this._datePipe.transform(date, 'dd. MMMM y');
    }
    return '';
  }

  get isTablet() {
    return this._environment.matchTablet();
  }

  get isDesktopLarge() {
    return this._environment.matchDesktopLarge();
  }

  get resultsPath() {
    return this._navigationService.getArticleSearchResultsPath(this.applicationService.activatedProcessId).path;
  }

  defaultBranch$ = this._availability.getDefaultBranch();

  selectedBranchId$ = this.applicationService.activatedProcessId$.pipe(
    switchMap((processId) => this.applicationService.getSelectedBranch$(processId)),
  );

  isOrderBranch$ = combineLatest([this.defaultBranch$, this.selectedBranchId$]).pipe(
    map(([defaultBranch, selectedBranch]) => {
      const branch = selectedBranch ?? defaultBranch;
      return branch.branchType !== 4;
    }),
  );

  stockTooltipText$ = combineLatest([this.defaultBranch$, this.selectedBranchId$]).pipe(
    map(([defaultBranch, selectedBranch]) => {
      if (defaultBranch?.branchType !== 4 && selectedBranch && defaultBranch.id !== selectedBranch?.id) {
        return 'Sie sehen den Bestand einer anderen Filiale.';
      }
      return '';
    }),
  );

  inStock$ = combineLatest([this.item$, this.selectedBranchId$, this.defaultBranch$]).pipe(
    debounceTime(100),
    filter(([item, branch, defaultBranch]) => !!item && !!defaultBranch),
    switchMap(([item, branch, defaultBranch]) =>
      this._stockService.getInStock$({ itemId: item.id, branchId: branch?.id ?? defaultBranch?.id }),
    ),
  );

  ssc$ = this._availability.sscsObs$.pipe(
    debounceTime(100),
    map((sscs) => {
      const updatedSsc = sscs?.find((ssc) => this.item?.id === ssc?.itemId);
      return {
        ssc: updatedSsc?.ssc ?? this.item?.catalogAvailability?.ssc,
        sscText: updatedSsc?.sscText ?? this.item?.catalogAvailability?.sscText,
      };
    }),
  );

  constructor(
    private _dateAdapter: DateAdapter,
    private _datePipe: DatePipe,
    private _articleSearchService: ArticleSearchService,
    public applicationService: ApplicationService,
    private _stockService: DomainInStockService,
    private _availability: DomainAvailabilityService,
    private _environment: EnvironmentService,
    private _navigationService: ProductCatalogNavigationService,
    private _store: Store,
  ) {
    super({
      selected: false,
      selectable: false,
    });
  }

  setSelected() {
    const isSelected = this._articleSearchService.selectedItemIds.includes(this.item?.id);
    this._articleSearchService.setSelected({ selected: !isSelected, itemId: this.item?.id });
  }

  async showTooltip() {
    const text = await this.stockTooltipText$.pipe(first()).toPromise();
    if (!text) {
      // Show Tooltip attached to branch selector dropdown
      this._store.dispatch({ type: 'OPEN_TOOLTIP_NO_BRANCH_SELECTED' });
    }
  }

  @HostBinding('style') get class() {
    return this.primaryOutletActive ? { height: '6.125rem' } : '';
  }
}
