import { DatePipe } from '@angular/common';
import { Component, ChangeDetectionStrategy, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { Config } from '@core/config';
import { DomainTaskCalendarService } from '@domain/task-calendar';
import { DisplayInfoDTO } from '@generated/swagger/eis-api';
import { DateAdapter, groupBy } from '@ui/common';
import { combineLatest, Observable, Subject } from 'rxjs';
import { first, map, takeUntil, debounceTime } from 'rxjs/operators';
import { TaskCalendarStore } from '../../task-calendar.store';

@Component({
  selector: 'page-task-search',
  templateUrl: 'task-search.component.html',
  styleUrls: ['task-search.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [DatePipe],
  standalone: false,
})
export class TaskSearchComponent implements OnInit, OnDestroy, AfterViewInit {
  private _onDestroy$ = new Subject<void>();
  private _taskCalendarKey = this._config.get('process.ids.taskCalendar');

  today = this.dateAdapter.today();
  todayKey = this.domainTaskCalendarService.getDateGroupKey(new Date().toISOString());
  byDate = (item: DisplayInfoDTO) =>
    this.domainTaskCalendarService.getDateGroupKey(item.taskDate || item.publicationDate);

  searchResults$ = this.taskCalendarStore.searchResults$;
  searchResultsLength$ = this.searchResults$.pipe(map((r) => r.length || 0));
  fetching$ = this.taskCalendarStore.selectFetchingSearch;

  displayItems$ = this.searchResults$.pipe(
    map((r) => {
      const grouped = groupBy(r, this.byDate);
      grouped.sort(
        (a, b) => this.dateAdapter.parseDate(a.group).getTime() - this.dateAdapter.parseDate(b.group).getTime(),
      );
      return grouped;
    }),
    // Sortierung der aufgaben nach Rot => Gelb => Grau => Grün
    map((grouped) =>
      grouped.map((g) => ({
        ...g,
        items: this.domainTaskCalendarService.sort(g.items, [
          'Overdue',
          'InProcess',
          'Approved',
          'Completed',
          'Removed',
        ]),
      })),
    ),
    // Entfernte ans ende der Gruppe setzen
    map((grouped) =>
      grouped.map((g) => ({
        ...g,
        items: g.items.sort((a, b) => this.domainTaskCalendarService.moveRemovedToEnd(a, b)),
      })),
    ),
  );

  showEmptyMessage$ = combineLatest([this.fetching$, this.searchResultsLength$, this.taskCalendarStore.hits$]).pipe(
    map(([fetching, length, hits]) => !fetching && length <= 0 && hits === 0),
  );

  previousBreadcrumb$: Observable<Breadcrumb> = this._breadcrumb
    .getBreadcrumbsByKeyAndTags$(this._taskCalendarKey, ['task-calendar'])
    .pipe(
      map((breadcrumbs) => {
        if (breadcrumbs?.length > 1) {
          return breadcrumbs[breadcrumbs.length - 2];
        }
        // Fallback wenn kein vorheriger Breadcrumb existiert
        return { path: '/filiale/task-calendar/tasks', name: 'Aufgaben', section: 'branch', key: 'task-calendar' };
      }),
    );

  constructor(
    private dateAdapter: DateAdapter,
    private taskCalendarStore: TaskCalendarStore,
    private domainTaskCalendarService: DomainTaskCalendarService,
    private _activatedRoute: ActivatedRoute,
    private _config: Config,
    private _breadcrumb: BreadcrumbService,
  ) {}

  ngOnInit() {
    this._activatedRoute.queryParams
      .pipe(takeUntil(this._onDestroy$), debounceTime(250))
      .subscribe(async (queryParams) => {
        this.taskCalendarStore.search({ clear: true });
        this.updateBreadcrumb(queryParams);
      });

    this.taskCalendarStore.focusSearchbar();
  }

  ngAfterViewInit(): void {
    this.taskCalendarStore.searchTarget$.pipe(takeUntil(this._onDestroy$), debounceTime(250)).subscribe((target) => {
      setTimeout(() => {
        document.getElementById(target)?.scrollIntoView();
      }, 0);
    });
  }

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

  async search() {
    const hits = await this.taskCalendarStore.hits$.pipe(first()).toPromise();
    const results = await this.taskCalendarStore.searchResults$.pipe(first()).toPromise();
    const fetching = await this.taskCalendarStore.selectFetchingSearch.pipe(first()).toPromise();

    if (hits > results.length && !fetching) {
      this.taskCalendarStore.search({});
    }
  }

  updateBreadcrumb(queryParams?: Params) {
    this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
      key: this._taskCalendarKey,
      name: queryParams?.main_qs || 'Suchergebnisse',
      path: '/filiale/task-calendar/search',
      tags: ['task-calendar', 'search'],
      section: 'branch',
      params: queryParams,
    });
  }
}
