import {
  ChangeDetectionStrategy,
  Component,
  effect,
  signal,
  untracked,
} from '@angular/core';
import { ButtonComponent } from '@isa/ui/buttons';
import { DialogContentDirective } from '../dialog-content.directive';
import {
  ValidatorFn,
  FormControl,
  ReactiveFormsModule,
  AsyncValidatorFn,
} from '@angular/forms';
import { toSignal } from '@angular/core/rxjs-interop';
import {
  InputControlDirective,
  TextFieldClearComponent,
  TextFieldComponent,
  TextFieldContainerComponent,
  TextFieldErrorsComponent,
} from '@isa/ui/input-controls';
import { ScannerButtonComponent } from '@isa/shared/scanner';
import { provideIcons } from '@ng-icons/core';
import { isaActionScanner } from '@isa/icons';

/**
 * Input data for the message dialog
 */
export interface TextInputDialogData {
  /** The message text to display in the dialog */
  message: string;

  /** The input field label to display */
  inputLabel?: string;

  /** The input field type (e.g., 'text', 'email', 'password', '10') */
  inputDefaultValue?: string;

  /** Optional validation for the input field */
  inputValidation?: TextInputValidation[];

  /** Optional custom text for the close button (defaults to "Verlassen" or equivalent) */
  closeText?: string;

  /** Optional custom text for the confirm button (defaults to "Speichern" or equivalent) */
  confirmText?: string;

  /** Optional async callback that is called when confirm button is clicked. If provided, dialog stays open until resolved/rejected */
  onConfirm?: (inputValue: string) => Promise<unknown>;
}

export interface TextInputValidation {
  /** The key to use for the validation error */
  errorKey: string;

  /** The validation function to apply */
  inputValidator: ValidatorFn | AsyncValidatorFn;

  /** Validation Error Message */
  errorText?: string;
}

export interface TextInputDialogResult {
  /** The value entered in the input field */
  inputValue?: string;
}

@Component({
  selector: 'ui-text-input-dialog',
  templateUrl: './text-input-dialog.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    ReactiveFormsModule,
    ButtonComponent,
    InputControlDirective,
    TextFieldClearComponent,
    TextFieldComponent,
    TextFieldContainerComponent,
    TextFieldErrorsComponent,
    ScannerButtonComponent,
  ],
  providers: [provideIcons({ isaActionScanner })],
})
export class TextInputDialogComponent extends DialogContentDirective<
  TextInputDialogData,
  TextInputDialogResult
> {
  control = new FormControl<string>(
    this.data?.inputDefaultValue || '',
    (this.data?.inputValidation
      ?.map((v) => v.inputValidator)
      .filter(Boolean) as ValidatorFn[]) ?? [],
  );

  #controlValue = toSignal(this.control.valueChanges);
  isLoading = signal(false);
  asyncError = signal<string | null>(null);

  constructor() {
    super();
    effect(() => {
      this.#controlValue();
      untracked(() => {
        if (this.asyncError()) {
          this.asyncError.set(null);
        }
      });
    });
  }

  onScan(value: string): void {
    this.control.setValue(value);
  }

  async onConfirm(): Promise<void> {
    if (this.control.invalid) {
      return;
    }

    const inputValue = this.control.value ?? '';

    // If no callback provided, close immediately with result
    if (!this.data?.onConfirm) {
      this.close({ inputValue });
      return;
    }

    try {
      this.isLoading.set(true);
      this.asyncError.set(null);
      await this.data.onConfirm(inputValue);
      this.close({ inputValue });
    } catch (error: any) {
      this.isLoading.set(false);
      this.asyncError.set(error?.message ?? 'Ein Fehler ist aufgetreten');
    }
  }
}
