import { signal, type Signal } from '@angular/core';
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { debounceTime, distinctUntilChanged } from 'rxjs';

const DEFAULT_DEBOUNCE_MS = 300;

export interface TableSearchAtom {
  readonly value: Signal<string>;
  readonly debouncedValue: Signal<string>;
  set(s: string): void;
}

/**
 * Atom: free-text search query. Single responsibility — owns the search
 * string. Exposes a debounced projection so consumers can react to settled
 * input without re-firing on every keystroke.
 *
 * MUST be invoked from an injection context (component constructor or
 * `runInInjectionContext`) because `toSignal` requires it.
 */
export function useTableSearch(
  initialValue = '',
  debounceMs = DEFAULT_DEBOUNCE_MS,
): TableSearchAtom {
  const valueSignal = signal(initialValue);
  const debouncedValue = toSignal(
    toObservable(valueSignal).pipe(debounceTime(debounceMs), distinctUntilChanged()),
    { initialValue },
  );

  return {
    value: valueSignal.asReadonly(),
    debouncedValue,
    set: (s: string) => valueSignal.set(s),
  };
}
