import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Filter } from '../models/filter.model';
import { FilterItem } from '../models/filter-item.model';
import { FilterMapping } from '../mappings/filter.mapping';
import { map } from 'rxjs/operators';
import { SearchService, ResponseArgsOfUISettingsDTO } from '@swagger/cat';

@Injectable({
  providedIn: 'root',
})
export class FilterService {
  constructor(private service: SearchService, private filterMapping: FilterMapping) {}

  selectFilterById(filters: Filter[], id: string): Observable<Filter[]> {
    const newFilterState = filters.map((filter: Filter) => {
      if (filter.id === id) {
        return { ...filter, expanded: true };
      }
      return { ...filter, expanded: false };
    });
    return of(newFilterState);
  }

  unselectFilterById(filters: Filter[], id: string): Observable<Filter[]> {
    const newFilterState = filters.map((filter: Filter) => {
      if (filter.id === id) {
        return { ...filter, expanded: false };
      }
      return { ...filter };
    });
    return of(newFilterState);
  }

  toggleFilterItemsById(filters: Filter[], id: string): Observable<Filter[]> {
    const newFilterState = filters.map((filter: Filter) => {
      if (filter.expanded === true) {
        const newItemsState = this.toggleItem(filter.items, id);
        return { ...filter, items: newItemsState };
      }
      return { ...filter };
    });
    return of(newFilterState);
  }

  toggleFilterItemsByName(filters: Filter[], name: string): Observable<Filter[]> {
    const newFilterState = filters.map((filter: Filter) => {
      const newItemsState = this.toggleItemByName(filter.items, name, filter.max ? filter.max : 0);
      return { ...filter, items: newItemsState };
    });
    return of(newFilterState);
  }

  private toggleItem(items: FilterItem[], id: string): FilterItem[] {
    return items.map((item: FilterItem) => {
      if (item.id === id) {
        return { ...item, selected: !item.selected };
      }
      return { ...item };
    });
  }

  private toggleItemByName(items: FilterItem[], name: string, max: number): FilterItem[] {
    if (max === 0) {
      return items.map((item: FilterItem) => {
        if (item.name === name) {
          return { ...item, selected: !item.selected };
        }
        return { ...item };
      });
    } else {
      let updatedItems = [
        ...items.map((item: FilterItem) => {
          if (item.name === name) {
            return { ...item, selected: !item.selected };
          }
          return { ...item };
        }),
      ];
      let selected = 0;
      let isSelectEvent = false;
      updatedItems.forEach((t) => {
        if (t.selected) {
          selected++;
        }
        if (t.name === name) {
          isSelectEvent = t.selected;
        }
      });
      let itemsToUselect = selected - max;
      if (isSelectEvent) {
        updatedItems = [
          ...updatedItems.map((item: FilterItem) => {
            if (item.name !== name && item.selected && itemsToUselect > 0) {
              itemsToUselect--;
              return { ...item, selected: false };
            }
            return { ...item };
          }),
        ];
      }
      return updatedItems;
    }
  }

  // service method to get the first 3 filters
  getFilters(): Observable<Filter[]> {
    return this.service
      .SearchSettings()
      .pipe(map((data: ResponseArgsOfUISettingsDTO) => this.filterMapping.fromUiSettingsDto(data.result).slice(0, 3)));
  }

  // service method to get filters metadata
  getFullFilter(): Observable<Filter[]> {
    return this.service
      .SearchSettings()
      .pipe(map((data: ResponseArgsOfUISettingsDTO) => this.filterMapping.fromUiSettingsDto(data.result)));
  }

  // service method to get the first 3 filters
  getNegativeFilters(): Observable<Filter[]> {
    return this.service.SearchSettings().pipe(
      map((data: ResponseArgsOfUISettingsDTO) => {
        const result = {
          ...data.result,
          filter: data.result.filter.filter((f) => f.key === 'format' || f.key === 'dbhwgr' || f.key === 'region' || f.key === 'stock'),
        };

        return this.filterMapping.fromUiSettingsDto(result);
      })
    );
  }
}
