import { Maybe } from '@/core';
import { NativeBridgeService } from '@/core/services';
import { ToastService } from '@/core/services/toast.service';
import { AbstractFormDialog } from '@/shared/abstractClasses';
import { InputComponent, KeyValueComponent } from '@/shared/components';
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
import { UikitFieldComponent } from '@/uikit';
import { Component, computed, inject, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { ButtonDirective } from 'primeng/button';
import { Select } from 'primeng/select';
import { catchError, throwError } from 'rxjs';
import { IPayment, IPosOrderResponse, TOrderPaymentTypes } from '../../models';
import { PosPaymentBridgeAbstract } from '../../services/payment-bridge.abstract';
import { PosPaymentBridgeService } from '../../services/payment-bridge.service';
import { PosLandingStore } from '../../store/main.store';

@Component({
  selector: 'pos-payment-form-dialog',
  templateUrl: './form-dialog.component.html',
  imports: [
    FormsModule,
    ReactiveFormsModule,
    InputComponent,
    FormFooterActionsComponent,
    KeyValueComponent,
    ButtonDirective,
    SharedDialogComponent,
    Select,
    UikitFieldComponent,
  ],
  providers: [{ provide: PosPaymentBridgeAbstract, useExisting: PosPaymentBridgeService }],
})
export class PosPaymentFormDialogComponent extends AbstractFormDialog<IPayment, IPosOrderResponse> {
  private readonly store = inject(PosLandingStore);
  private readonly paymentBridge = inject(PosPaymentBridgeAbstract);
  private readonly nativeBridgeService = inject(NativeBridgeService);
  private readonly toastServices = inject(ToastService);

  readonly totalAmount = computed(() => this.store.orderPricingInfo().totalAmount);

  readonly remainedAmount = signal(this.totalAmount());
  setOffMax = signal(this.remainedAmount());
  cashMax = signal(this.remainedAmount());
  terminalsMax = signal([this.remainedAmount()]);

  submitOrderLoading = computed(() => this.store.submitOrderLoading());

  payByTerminalSteps = Array.from({ length: 10 }, (_, i) => ({
    value: i + 1,
    label: `${i + 1} مرحله‌ای`,
  }));

  selectedPayByTerminalStep = signal(1);
  payedInTerminal = signal<Array<number>>([]);

  private restorePaymentCallback: Maybe<() => void> = null;
  private readonly injectedPaymentResultHandler = (payload: unknown) => {
    this.toastServices.success({ text: 'شد شد شد شد شد' });
    // this.handlePaymentResult(payload);
  };

  ngOnViewInit() {
    this.restorePaymentCallback = this.paymentBridge.registerPaymentResultListener(
      this.injectedPaymentResultHandler,
    );
  }

  private initForm = () => {
    const form = this.fb.group({
      set_off: [0],
      cash: [0],
      terminals: this.fb.array([this.fb.control(0)]),
    });

    form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
      const terminalTotal =
        (value.terminals || []).reduce((acc, curr) => (acc || 0) + (curr || 0), 0) || 0;

      const totalValue = (value.cash || 0) + (value.set_off || 0) + terminalTotal;
      const remainedAmount = this.totalAmount() - totalValue;

      const setOffMax = remainedAmount + (value.set_off || 0);
      const cashMax = remainedAmount + (value.cash || 0);

      form.controls.set_off.clearValidators();
      form.controls.set_off.addValidators([Validators.max(setOffMax)]);
      if (!setOffMax) {
        form.controls.set_off.disable({
          onlySelf: true,
        });
      } else {
        form.controls.set_off.enable({
          onlySelf: true,
        });
      }

      form.controls.cash.clearValidators();
      form.controls.cash.addValidators([Validators.max(cashMax)]);
      if (!cashMax) {
        form.controls.cash.disable({
          onlySelf: true,
        });
      } else {
        form.controls.cash.enable({
          onlySelf: true,
        });
      }

      form.controls.terminals.controls.forEach((terminal, i) => {
        terminal.clearValidators();
        this.terminalsMax.update((max) => {
          const terminalMax = remainedAmount + (terminal.value || 0);
          terminal.addValidators([Validators.max(terminalMax)]);
          if (terminalMax) {
            terminal.enable({
              onlySelf: true,
            });
          } else {
            terminal.disable({
              onlySelf: true,
            });
          }
          return max.map((m, index) => (index === i ? terminalMax : m));
        });
      });

      this.remainedAmount.set(remainedAmount);
      this.cashMax.set(cashMax);
      this.setOffMax.set(setOffMax);
    });

    return form;
  };

  form = this.initForm();
  get terminalControls() {
    return this.form.controls.terminals.controls as FormControl<number | null>[];
  }

  changePayByTerminalSteps(steps: number) {
    const normalizedSteps = Math.max(1, Number(steps) || 1);
    this.selectedPayByTerminalStep.set(normalizedSteps);

    const terminals = this.form.controls.terminals;
    const currentLength = terminals.length;

    if (normalizedSteps > currentLength) {
      for (let i = currentLength; i < normalizedSteps; i += 1) {
        terminals.push(this.fb.control(0));
        const terminalMax = this.remainedAmount();
        this.form.controls.terminals.controls[i].addValidators([Validators.max(terminalMax)]);
        this.terminalsMax.update((max) => [...max, terminalMax]);
      }
      return;
    }

    if (normalizedSteps < currentLength) {
      const removedSum = terminals.controls
        .slice(normalizedSteps)
        .reduce((acc, control) => acc + (control.value || 0), 0);

      this.remainedAmount.update((value) => value + removedSum);

      while (terminals.length > normalizedSteps) {
        terminals.removeAt(terminals.length - 1);
      }

      // terminals.at(0)?.setValue(firstValue + removedSum);
    }
  }

  fillTerminalRemained(index: number) {
    this.fillRemained('TERMINAL', index);
  }

  fillRemained(type: TOrderPaymentTypes, _terminalIndex?: number) {
    switch (type) {
      case 'TERMINAL':
        const terminalIndex = _terminalIndex ?? 0;
        this.form.controls.terminals
          .at(terminalIndex)
          ?.setValue(
            (this.form.controls.terminals.at(terminalIndex)?.value || 0) + this.remainedAmount(),
          );
        break;

      case 'CASH':
        this.form.controls.cash.setValue(
          (this.form.controls.cash.value || 0) + this.remainedAmount(),
        );
        break;

      case 'SET_OFF':
        this.form.controls.set_off.setValue(
          (this.form.controls.set_off.value || 0) + this.remainedAmount(),
        );
        break;
    }
  }

  override showSuccessMessage = false;

  ngOnDestroy() {
    this.restorePaymentCallback?.();
  }

  override submitForm() {
    if (this.remainedAmount() > 0) {
      return this.toastServices.warn({
        text: 'فاکتور تسویه نشده است. لطفا مبلغ پرداخت را کامل کنید..',
      });
    }

    const rawPayment = this.form.getRawValue();
    const payment: IPayment = {
      cash: Number(rawPayment.cash || 0),
      set_off: Number(rawPayment.set_off || 0),
      terminals: (rawPayment.terminals || []).map((value) => Number(value || 0)),
    };

    this.store.setPayment(payment);

    const terminalPaymentIsDone = this.checkTerminalPayments();

    if (terminalPaymentIsDone) {
      this.store
        .submitOrder()
        .pipe(
          catchError((err) => {
            return throwError(() => err);
          }),
        )
        .subscribe((res) => {
          this.close();
          this.onSubmit.emit(res);
        });
    }
  }

  private checkTerminalPayments(): boolean {
    this.form.controls.terminals.controls = this.form.controls.terminals.controls.filter(
      (control) => control.value,
    );
    const terminalPayments = this.form.controls.terminals.controls.map(
      (terminal) => terminal.value!,
    );

    this.selectedPayByTerminalStep.set(terminalPayments.length || 1);

    if (terminalPayments.length) {
      if (this.nativeBridgeService.isEnabled()) {
        for (let i in terminalPayments) {
          const terminal = terminalPayments[i];
          this.toastServices.info({ text: 'در حال پردازش پرداخت با دستگاه...', life: 3000 });
          this.payByTerminal(parseInt(i), terminal);
          break;
        }
      } else {
        this.toastServices.error({
          text: 'امکان ارتباط با دستگاه پرداخت میسر نیست.',
        });
        return false;
      }

      return false;
    }

    return true;
  }

  private payByTerminal(id: number, amount: number) {
    const payResult = this.nativeBridgeService.pay({
      amount,
      id: id.toString(),
    });

    // if (!payResult.success) {
    //   return this.toastServices.warn({
    //     text: payResult.error || 'پرداخت با دستگاه انجام نشد. لطفا دوباره تلاش کنید.',
    //   });
    // }
  }

  override onSuccess(response: IPosOrderResponse): void {}

  private extractAmountFromPaymentResult(payload: unknown): number | null {
    if (!payload || typeof payload !== 'object') return null;
    const amount = (payload as { amount?: unknown }).amount;
    if (typeof amount === 'number' && Number.isFinite(amount)) {
      return amount;
    }
    return null;
  }
}
