import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  input,
  signal,
  ViewEncapsulation,
} from '@angular/core';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { isaActionCheck, isaActionClose } from '@isa/icons';
import { FilterService, CheckboxFilterInput } from '../../core';
import { InputType } from '../../types';
import { CheckboxComponent } from '@isa/ui/input-controls';
import { OverlayModule } from '@angular/cdk/overlay';
import { CheckboxInputControlComponent } from './checkbox-input-control.component';
import {
  checkboxSelectedHelper,
  getAllCheckboxOptionsHelper,
  filterCheckboxOptionsHelper,
} from '../../helpers';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'filter-checkbox-input',
  templateUrl: './checkbox-input.component.html',
  styleUrls: ['./checkbox-input.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  standalone: true,
  imports: [
    OverlayModule,
    CheckboxInputControlComponent,
    CheckboxComponent,
    FormsModule,
    NgIcon,
  ],
  host: {
    '[class]': "['filter-checkbox-input']",
    '[formGroup]': 'checkboxes',
  },
  providers: [provideIcons({ isaActionCheck, isaActionClose })],
})
export class CheckboxInputComponent {
  readonly filterService = inject(FilterService);

  inputKey = input.required<string>();

  input = computed<CheckboxFilterInput>(() => {
    const inputs = this.filterService.inputs();
    const inputKey = this.inputKey();
    return inputs.find(
      (input) => input.key === inputKey && input.type === InputType.Checkbox,
    ) as CheckboxFilterInput;
  });

  /**
   * Computed property that determines if the checkbox input has a maximum options limit configured.
   *
   * This property is used to conditionally show/hide the "Select All" control in the template.
   * When a maximum limit is set, the "Select All" functionality is disabled to prevent
   * users from selecting more items than allowed, which would result in automatic deselection
   * due to the FIFO enforcement in the filter service.
   *
   * @returns True if the input has a maximum options limit greater than 0, false otherwise
   *
   * @example
   * ```typescript
   * // In template:
   * // @if (!hasMaxOptions()) {
   * //   <label>Select All</label>
   * // }
   * ```
   */
  hasMaxOptions = computed(() => {
    const input = this.input();
    return input.maxOptions && input.maxOptions > 0;
  });

  options = computed(() => {
    const input = this.input();
    const options = input?.options || [];
    const query = this.filterQuery();

    return filterCheckboxOptionsHelper(options, query);
  });

  filterControlVisible = computed(() => {
    const input = this.input();
    const allOptions = getAllCheckboxOptionsHelper(input);
    // Show control if there are more than 20 options
    return allOptions.length > 20;
  });

  filterPlaceholder = computed(() => {
    const input = this.input();
    return `${input.label} suchen...`;
  });

  filterQuery = signal<string>('');

  allChecked = computed(() => {
    const input = this.input();
    const allOptions = getAllCheckboxOptionsHelper(input);

    // Only check leaf options (options without children)
    // Parent options are automatically considered checked if all their children are checked
    const leafOptions = allOptions.filter(
      (option) => !option.values || option.values.length === 0,
    );

    return leafOptions.every(
      (option) =>
        checkboxSelectedHelper(this.filterService.inputs(), option) ===
        'checked',
    );
  });

  toggleSelection() {
    const filterGroup = this.input().group;
    const filterGroupKey = this.inputKey();
    const options = this.input()?.options || [];
    const allChecked = this.allChecked();
    this.filterService.toggleAllCheckboxOptions({
      group: filterGroup,
      groupKey: filterGroupKey,
      checkboxOptions: options,
      selected: !allChecked,
    });
  }
}
