import { CurrencyPipe, DatePipe, LowerCasePipe } from "@angular/common";
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  input,
} from "@angular/core";
import { isaActionClose, ProductFormatIconGroup } from "@isa/icons";
import {
  getReceiptItemAction,
  getReceiptItemQuantity,
  ReceiptItem,
  ReturnDetailsStore,
} from "@isa/oms/data-access";
import { ProductImageDirective } from "@isa/shared/product-image";
import { ItemRowComponent } from "@isa/ui/item-rows";
import { NgIconComponent, provideIcons } from "@ng-icons/core";
import { ReturnDetailsOrderGroupItemControlsComponent } from "../return-details-order-group-item-controls/return-details-order-group-item-controls.component";
import { ProductRouterLinkDirective } from "@isa/shared/product-router-link";

@Component({
  selector: "oms-feature-return-details-order-group-item",
  templateUrl: "./return-details-order-group-item.component.html",
  styleUrls: ["./return-details-order-group-item.component.scss"],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [
    ItemRowComponent,
    ProductImageDirective,
    NgIconComponent,
    DatePipe,
    CurrencyPipe,
    LowerCasePipe,
    ReturnDetailsOrderGroupItemControlsComponent,
    ProductRouterLinkDirective,
  ],
  providers: [provideIcons({ ...ProductFormatIconGroup, isaActionClose })],
})
export class ReturnDetailsOrderGroupItemComponent {
  #store = inject(ReturnDetailsStore);

  /**
   * The receipt item data to display.
   * Contains all information about a product including details, price, and return eligibility.
   */
  item = input.required<ReceiptItem>();

  /**
   * Two-way binding for the selection state of the item.
   * Indicates whether the item is currently selected for return.
   */
  selected = computed<boolean>(() => {
    const selectedIds = this.#store.selectedItemIds();
    const item = this.item();
    return selectedIds.includes(item.id);
  });

  /**
   * Holds the return eligibility information from the API.
   * Contains both the eligibility result (boolean) and any message explaining the reason.
   * This signal may be undefined if the eligibility check hasn't completed yet.
   */
  canReturn = this.#store.getCanReturn(this.item);

  /**
   * Computes whether the item can be returned.
   * Prefers the endpoint result if available, otherwise checks the item's actions.
   */
  canReturnReceiptItem = computed(() => {
    const returnableItems = this.#store.returnableItems();
    const item = this.item();
    return returnableItems.some(
      (returnableItem) => returnableItem.id === item.id,
    );
  });

  /**
   * Computes the message explaining the return eligibility.
   * Prefers the endpoint message if available, otherwise uses the item's action description.
   */
  canReturnMessage = computed(() => {
    const item = this.item();
    const canReturnAction = getReceiptItemAction(item, "canReturn");

    if (canReturnAction?.description) {
      return canReturnAction.description;
    }

    const canReturnMessage = this.canReturn()?.message;

    return canReturnMessage ?? "";
  });

  /**
   * The original quantity of the item as recorded in the order.
   * This value is retrieved from the store and represents the total number of units
   * initially purchased for this receipt item.
   *
   * @readonly
   * @returns {number} The original quantity of the item in the order.
   */
  quantity = computed(() => {
    const item = this.item();
    return getReceiptItemQuantity(item);
  });

  /**
   * The currently available quantity of the item for return.
   * This value is computed based on the item's current state and may be less than
   * the original quantity if some units have already been returned or are otherwise unavailable.
   *
   * @readonly
   * @returns {number} The number of units available for return.
   */
  availableQuantity = computed(() => {
    const item = this.item();
    return this.#store.availableQuantityMap()[item.id];
  });
}
