import {
  ValidationErrorCollection,
  ValidationErrorDetail,
  extractOrPushError,
} from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import { CreateCustomerInvoiceRequestDTO } from "../../../common";
import {
  CustomerInvoiceItem,
  CustomerInvoiceItemDescription,
  ItemAmount,
  ItemDiscount,
  ItemQuantity,
} from "../../domain";
import { hasNoUndefinedFields } from "./has-no-undefined-fields";

export function mapDTOToCustomerInvoiceItemsProps(
  dtoItems: Pick<CreateCustomerInvoiceRequestDTO, "items">["items"]
): Result<CustomerInvoiceItem[], ValidationErrorCollection> {
  const errors: ValidationErrorDetail[] = [];
  const items: CustomerInvoiceItem[] = [];

  dtoItems.forEach((item, index) => {
    const path = (field: string) => `items[${index}].${field}`;

    const description = extractOrPushError(
      CustomerInvoiceItemDescription.create(item.description),
      path("description"),
      errors
    );

    const quantity = extractOrPushError(
      ItemQuantity.create({
        value: Number(item.quantity),
      }),
      path("quantity"),
      errors
    );

    const unitPrice = extractOrPushError(
      ItemAmount.create({
        value: item.unitPrice.amount,
        scale: item.unitPrice.scale,
        currency_code: item.unitPrice.currency,
      }),
      path("unit_price"),
      errors
    );

    const discount = extractOrPushError(
      ItemDiscount.create({
        value: item.discount.amount,
        scale: item.discount.scale,
      }),
      path("discount"),
      errors
    );

    if (errors.length === 0) {
      const itemProps = {
        description: description,
        quantity: quantity,
        unitPrice: unitPrice,
        discount: discount,
      };

      if (hasNoUndefinedFields(itemProps)) {
        // Validar y crear el item de factura
        const itemOrError = CustomerInvoiceItem.create(itemProps);

        if (itemOrError.isSuccess) {
          items.push(itemOrError.data);
        } else {
          errors.push({ path: `items[${index}]`, message: itemOrError.error.message });
        }
      }
    }

    if (errors.length > 0) {
      return Result.fail(new ValidationErrorCollection(errors));
    }
  });

  return Result.ok(items);
}
