import {
  ChangeDetectionStrategy,
  Component,
  computed,
  effect,
  inject,
  input,
  output,
  untracked,
  ViewEncapsulation,
} from '@angular/core';
import {
  UiSearchBarClearComponent,
  UiSearchBarComponent,
} from '@isa/ui/search-bar';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { IconButtonColor, IconButtonComponent } from '@isa/ui/buttons';
import { provideIcons } from '@ng-icons/core';
import { isaActionSearch, isaActionScanner } from '@isa/icons';
import { FilterService, TextFilterInput } from '../../core';
import { InputType, SearchTrigger } from '../../types';
import { toSignal } from '@angular/core/rxjs-interop';
import { ScannerButtonComponent } from '@isa/shared/scanner';

/**
 * A search bar input component with integrated scanner functionality for filtering systems.
 * 
 * This component provides a unified search experience with text input and barcode scanning capabilities.
 * It integrates with the FilterService to manage search state and emit search trigger events.
 * 
 * @example
 * ```html
 * <filter-search-bar-input
 *   inputKey="qs"
 *   appearance="main"
 *   buttonColor="brand"
 *   (triggerSearch)="handleSearch($event)">
 * </filter-search-bar-input>
 * ```
 */
@Component({
  selector: 'filter-search-bar-input',
  templateUrl: './search-bar-input.component.html',
  styleUrls: ['./search-bar-input.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  standalone: true,
  imports: [
    UiSearchBarComponent,
    IconButtonComponent,
    ReactiveFormsModule,
    UiSearchBarClearComponent,
    ScannerButtonComponent,
  ],
  host: {
    '[class]': "['filter-search-bar-input', appearanceClass()]",
  },
  providers: [provideIcons({ isaActionSearch, isaActionScanner })],
})
export class SearchBarInputComponent {
  /**
   * FilterService instance for managing search filter state.
   * @readonly
   */
  readonly filterService = inject(FilterService);

  /**
   * Form control for managing the search input value.
   */
  control = new FormControl();

  /**
   * Signal that tracks changes to the form control's value.
   */
  /**
   * Signal that tracks changes to the form control's value.
   */
  valueChanges = toSignal(this.control.valueChanges);

  /**
   * The unique key identifier for this input in the filter system.
   * @required
   */
  inputKey = input.required<string>();

  /**
   * The color scheme for the search button.
   * @default 'brand'
   */
  buttonColor = input<IconButtonColor>('brand');

  /**
   * The visual appearance variant of the search bar.
   * - 'main': Primary search bar with prominent styling
   * - 'results': Secondary search bar for filtering results
   * @default 'main'
   */
  appearance = input<'main' | 'results'>('main');

  /**
   * Computed CSS class name based on the appearance variant.
   * @returns CSS class string for styling the component appearance
   */
  appearanceClass = computed(
    () => `filter-search-bar-input__${this.appearance()}`,
  );

  /**
   * Computed signal that retrieves and manages the text filter input configuration.
   * Automatically synchronizes the form control value with the filter service state.
   * 
   * @returns The TextFilterInput configuration object
   * @throws {Error} When no input is found for the specified key
   */
  input = computed<TextFilterInput>(() => {
    const inputs = this.filterService.inputs();
    const input = inputs.find(
      (input) => input.key === this.inputKey() && input.type === InputType.Text,
    ) as TextFilterInput;

    if (!input) {
      throw new Error(`Input not found for key: ${this.inputKey()}`);
    }

    this.control.setValue(input.value);
    this.control.updateValueAndValidity();

    return input;
  });

  /**
   * Output event emitter that signals when a search should be triggered.
   * Emits different SearchTrigger types based on the action performed:
   * - 'input': Manual text input or search button click
   * - 'scan': Barcode scanning result
   */
  triggerSearch = output<SearchTrigger>();

  /**
   * Constructor sets up reactive effect to sync form control changes with filter service.
   * The effect tracks value changes and updates the filter service when the local
   * control value differs from the stored filter value.
   */
  constructor() {
    effect(() => {
      this.valueChanges();
      untracked(() => {
        if (this.input().value !== this.control.value) {
          this.filterService.setInputTextValue(
            this.inputKey(),
            this.control.value,
          );
        }
      });
    });
  }

  /**
   * Handles barcode scan results from the scanner component.
   * Updates the filter service with the scanned value and triggers a search.
   * 
   * @param value - The scanned barcode value, or null if scan failed
   */
  onScan(value: string | null): void {
    if (value) {
      this.filterService.setInputTextValue(this.inputKey(), value);
      this.triggerSearch.emit('scan');
    }
  }
}
