/**
 * Service de gestion des filtres avancés
 */

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { FilterGroup, FilterCondition, LogicalOperator } from '../models/filter.models';

@Injectable({
  providedIn: 'root'
})
export class FilterService {
  private filtersSubject = new BehaviorSubject<FilterGroup | null>(null);
  public filters$: Observable<FilterGroup | null> = this.filtersSubject.asObservable();

  /**
   * Définit les filtres actifs
   */
  setFilters(filters: FilterGroup | null): void {
    this.filtersSubject.next(filters);
  }

  /**
   * Récupère les filtres actifs
   */
  getFilters(): FilterGroup | null {
    return this.filtersSubject.value;
  }

  /**
   * Réinitialise tous les filtres
   */
  clearFilters(): void {
    this.filtersSubject.next(null);
  }

  /**
   * Compte le nombre de conditions actives
   */
  getActiveFiltersCount(filters: FilterGroup | null): number {
    if (!filters) return 0;
    return this.countConditions(filters);
  }

  /**
   * Compte récursivement les conditions dans un groupe
   */
  private countConditions(item: FilterGroup | FilterCondition): number {
    if (this.isFilterGroup(item)) {
      return item.conditions.reduce(
        (sum, condition) => sum + this.countConditions(condition),
        0
      );
    }
    return 1;
  }

  /**
   * Vérifie si un élément est un groupe de filtres
   */
  private isFilterGroup(item: FilterGroup | FilterCondition): item is FilterGroup {
    return 'conditions' in item && Array.isArray((item as FilterGroup).conditions);
  }

  /**
   * Crée un nouveau groupe de filtres vide
   */
  createEmptyGroup(logicalOperator: LogicalOperator = LogicalOperator.AND): FilterGroup {
    return {
      id: this.generateId(),
      logicalOperator,
      conditions: []
    };
  }

  /**
   * Crée une nouvelle condition vide
   */
  createEmptyCondition(field: string = ''): FilterCondition {
    return {
      id: this.generateId(),
      field,
      operator: null as any,
      value: null
    };
  }

  /**
   * Génère un ID unique
   */
  private generateId(): string {
    return `filter_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * Convertit les filtres en objet pour l'API
   */
  buildFilterQuery(filters: FilterGroup | null): any {
    if (!filters) return null;
    return filters;
  }

  /**
   * Valide qu'une condition est complète
   */
  isConditionValid(condition: FilterCondition): boolean {
    if (!condition.field || !condition.operator) {
      return false;
    }

    // Les opérateurs isEmpty et isNotEmpty ne nécessitent pas de valeur
    const noValueOperators = ['isEmpty', 'isNotEmpty'];
    if (noValueOperators.includes(condition.operator)) {
      return true;
    }

    // Les autres opérateurs nécessitent une valeur
    if (condition.value === null || condition.value === undefined || condition.value === '') {
      return false;
    }

    // Les opérateurs "between" nécessitent 2 valeurs
    const twoValueOperators = ['between', 'dateBetween'];
    if (twoValueOperators.includes(condition.operator)) {
      return condition.value2 !== null && condition.value2 !== undefined && condition.value2 !== '';
    }

    return true;
  }

  /**
   * Valide qu'un groupe est complet
   */
  isGroupValid(group: FilterGroup): boolean {
    if (!group.conditions || group.conditions.length === 0) {
      return false;
    }

    return group.conditions.every(item => {
      if (this.isFilterGroup(item)) {
        return this.isGroupValid(item);
      }
      return this.isConditionValid(item);
    });
  }
}
