import {
  ChangeDetectionStrategy,
  Component,
  effect,
  ElementRef,
  inject,
  input,
  signal,
  viewChild,
} from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import {
  Product,
  ReturnProcessProductQuestion,
  ReturnProcessStore,
} from '@isa/oms/data-access';
import { TextButtonComponent } from '@isa/ui/buttons';
import {
  InputControlDirective,
  TextFieldClearComponent,
  TextFieldComponent,
  TextFieldContainerComponent,
  TextFieldErrorsComponent,
} from '@isa/ui/input-controls';
import { rxMethod } from '@ngrx/signals/rxjs-interop';
import { filter, pipe, switchMap, tap } from 'rxjs';
import { CatalougeSearchService } from '@isa/catalogue/data-access';
import { tapResponse } from '@ngrx/operators';
import { from } from 'rxjs';
import { ProductImageDirective } from '@isa/shared/product-image';
import { provideIcons } from '@ng-icons/core';
import { isaActionScanner } from '@isa/icons';
import { ScannerButtonComponent } from '@isa/shared/scanner';
import { ProductRouterLinkDirective } from '@isa/shared/product-router-link';
import { toSignal } from '@angular/core/rxjs-interop';
import { eanValidator } from '@isa/utils/ean-validation';

@Component({
  selector: 'oms-feature-return-process-product-question',
  templateUrl: './return-process-product-question.component.html',
  styleUrls: ['./return-process-product-question.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    ReactiveFormsModule,
    InputControlDirective,
    TextButtonComponent,
    TextFieldContainerComponent,
    TextFieldErrorsComponent,
    TextFieldComponent,
    TextFieldClearComponent,
    ProductImageDirective,
    ScannerButtonComponent,
    ProductRouterLinkDirective,
  ],
  providers: [provideIcons({ isaActionScanner })],
})
export class ReturnProcessProductQuestionComponent {
  #returnProcessStore = inject(ReturnProcessStore);
  #catalogueSearchService = inject(CatalougeSearchService);

  inputElement = viewChild<ElementRef<HTMLInputElement>>('inputRef');

  returnProcessId = input.required<number>();

  question = input.required<ReturnProcessProductQuestion>();

  control = new FormControl<string>('', [Validators.required, eanValidator]);
  valueChanges = toSignal(this.control.valueChanges);

  product = signal<Product | undefined>(undefined);
  status = signal<{ fetching: boolean; hasResult?: boolean }>({
    fetching: false,
  });

  constructor() {
    effect(() => {
      const valueChanged = this.valueChanges();
      if (valueChanged) {
        this.control.setErrors(null);
        this.status.set({ fetching: false, hasResult: undefined });
      }
    });

    effect(() => {
      const product = this.#returnProcessStore.entityMap()[
        this.returnProcessId()
      ]?.answers[this.question().key] as Product;

      if (product) {
        this.control.setValue(product.ean ?? null);
        this.product.set(product);
      } else {
        this.inputElement()?.nativeElement?.focus();
      }
    });
  }

  resetProduct() {
    this.product.set(undefined);
    this.#returnProcessStore.removeAnswer(
      this.returnProcessId(),
      this.question().key,
    );
    this.inputElement()?.nativeElement?.focus();
  }

  onScan(value: string | null) {
    if (value) {
      this.control.setValue(value);
      this.check();
    }
  }

  check = rxMethod<void>(
    pipe(
      filter(() => this.control.valid),
      tap(() => {
        this.control.updateValueAndValidity();
        this.status.set({ fetching: true, hasResult: undefined });
      }),
      switchMap(() =>
         
        from(
          this.#catalogueSearchService.searchByEans([this.control.value!]),
        ).pipe(
          tapResponse({
            next: (value) => {
              if (!!value[0] && value[0].product) {
                this.product.set(value[0]?.product);
                this.#returnProcessStore.setAnswer(
                  this.returnProcessId(),
                  this.question().key,
                  value[0]?.product,
                );
                this.status.set({ fetching: false, hasResult: undefined });
              } else {
                this.resetProduct();
                this.status.set({ fetching: false, hasResult: false });
              }
            },
            error: (error) => {
              this.status.set({ fetching: false, hasResult: false });
              console.error(error);
            },
          }),
        ),
      ),
    ),
  );
}
