import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  model,
  resource,
} from '@angular/core';
import { QuantityAndReasonItemComponent } from './quantity-and-reason-item.component';
import {
  ButtonComponent,
  TextButtonComponent,
  IconButtonComponent,
} from '@isa/ui/buttons';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { isaActionPlus, isaActionClose } from '@isa/icons';
import {
  RemissionSearchService,
  RemissionStore,
  ReturnItem,
} from '@isa/remission/data-access';
import { DialogContentDirective, injectFeedbackDialog } from '@isa/ui/dialog';
import { BatchResponseArgs } from '@isa/common/data-access';
import { Item } from '@isa/catalogue/data-access';
import { ProductInfoComponent } from '@isa/remission/shared/product';

export type SelectRemiQuantityAndReasonDialogData = {
  item: Item;
  inStock: number;
};

export type SelectRemiQuantityAndReasonDialogResult =
  | undefined
  | Array<ReturnItem>;

export interface QuantityAndReason {
  quantity: number;
  reason: string;
}

@Component({
  selector: 'remi-select-remi-quantity-and-reason-dialog',
  templateUrl: './select-remi-quantity-and-reason-dialog.component.html',
  styleUrls: ['./select-remi-quantity-and-reason-dialog.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [
    QuantityAndReasonItemComponent,
    TextButtonComponent,
    NgIcon,
    ButtonComponent,
    IconButtonComponent,
    ProductInfoComponent,
  ],
  providers: [provideIcons({ isaActionPlus, isaActionClose })],
})
export class SelectRemiQuantityAndReasonDialogComponent extends DialogContentDirective<
  SelectRemiQuantityAndReasonDialogData,
  SelectRemiQuantityAndReasonDialogResult
> {
  #remiService = inject(RemissionSearchService);
  #remiStore = inject(RemissionStore);
  #feedbackDialog = injectFeedbackDialog();

  initialItem: QuantityAndReason = { quantity: 0, reason: '' };

  quantitiesAndResons = model<QuantityAndReason[]>([this.initialItem]);

  addQuantityReasonItem(): void {
    this.quantitiesAndResons.update((items) => [...items, this.initialItem]);
  }

  removeQuantityReasonItem(position: number): void {
    const currentItems = this.quantitiesAndResons();
    if (currentItems.length > 1) {
      this.quantitiesAndResons.update((items) =>
        items.filter((_, index) => index !== position),
      );
    }
  }

  setQuantityAndReason(position: number, qar: QuantityAndReason): void {
    this.quantitiesAndResons.update((items) => {
      const newItems = [...items];
      newItems[position] = qar;
      return newItems;
    });
  }

  params = computed(() => {
    const items = this.quantitiesAndResons();
    const item = this.data.item;

    if (!item) {
      return [];
    }

    return items.map((qar) => ({
      item,
      quantity: qar.quantity,
      reason: qar.reason,
    }));
  });

  canAddToRemiListResource = resource({
    params: this.params,
    loader: async ({ params, abortSignal }) => {
      if (
        !this.data.item ||
        params.some((p) => !p.reason) ||
        params.some((p) => !p.quantity)
      ) {
        return undefined;
      }

      const maxQuantityErrors = params.filter((p) => !(p.quantity <= 999));
      if (maxQuantityErrors.length > 0) {
        const errRes: BatchResponseArgs<ReturnItem> = {
          completed: false,
          error: true,
          total: maxQuantityErrors.length,
          invalidProperties: {
            quantity: 'Die Menge darf maximal 999 sein.',
          },
        };
        return errRes;
      }

      return this.#remiService.canAddItemToRemiList(params, abortSignal);
    },
  });

  canReturn = computed(() => {
    const results = this.canAddToRemiListResource.value();

    if (!results) {
      return false;
    }

    if (results.failed && results.failed.length > 0) {
      return false;
    }

    if (
      results.successful &&
      results.successful.length === this.quantitiesAndResons().length
    ) {
      return true;
    }

    return false;
  });

  canReturnErrors = computed(() => {
    const results = this.canAddToRemiListResource.value();
    if (results?.invalidProperties) {
      return Object.values(results.invalidProperties);
    }

    if (!results?.failed) {
      return [];
    }
    return results.failed.map((item) =>
      item.invalidProperties
        ? Object.values(item.invalidProperties).join(', ')
        : [],
    ) as string[];
  });

  async addToRemiList() {
    const canAddValue = this.canAddToRemiListResource.value();

    if (!canAddValue) {
      return;
    }

    if (canAddValue.failed?.length) {
      return;
    }

    // #5273, #4768 Fix - Items dürfen nur zur Pflichtremission hinzugefügt werden
    const result: Array<ReturnItem> = await this.#remiService.addToList(
      this.params(),
    );

    this.#feedbackDialog({
      data: {
        message: this.#remiStore.remissionStarted()
          ? 'Wurde zum Warenbegleitschein hinzugefügt'
          : 'Wurde zur Remi Liste hinzugefügt',
      },
    });

    this.close(result);
  }
}
