import { IV_Product as CwIVProduct } from "../../generated/prisma/client";
import { Translation, skipRow } from "./types";
import { TranslationContext } from "./context";

type ApiProductDataRecord = {
  id: number;
  qty: number;
  internalNote?: string | null;
  shortDescription?: string | null;
  description?: string | null;
  sequenceNumber?: number | null;
  procurementNotes?: string | null;
  productNarrative?: string | null;
  unitPrice: number;
  unitCost: number;
  listPrice: number;
  discount: number;
  recurringRevenue: number;
  recurringCost: number;
  qtyPicked: number;
  qtyShipped: number;
  cancelReason?: string | null;
  cancelQty?: number | null;
  billableFlag: boolean;
  taxableFlag: boolean;
  invoiceFlag: boolean;
  recurringFlag: boolean;
  poApprovedFlag: boolean;
  calcPriceFlag: boolean;
  calcCostFlag: boolean;
  cancelFlag: boolean;
  catalogItemId: number;
  corporateLocationId: number;
  serviceTicketId?: number | null;
  opportunityId?: number | null;
  updatedById?: string | null;
  createdById?: string | null;
  closedById?: string | null;
  cancelById: string;
  closedAt?: Date | null;
  cancelledAt?: Date | null;
  createdAt: Date;
  updatedAt: Date;
};

const toInt = (value: unknown, fallback = 0): number => {
  if (value == null) return fallback;
  const numeric = Number(value);
  if (!Number.isFinite(numeric)) return fallback;
  return Math.trunc(numeric);
};

const toNumber = (value: unknown, fallback = 0): number => {
  if (value == null) return fallback;
  const numeric = Number(value);
  return Number.isFinite(numeric) ? numeric : fallback;
};

export const productDataTranslation: Translation<
  CwIVProduct,
  ApiProductDataRecord,
  TranslationContext
> = {
  values: [
    { from: "ivProductRecId", to: "id" },
    {
      from: "quantity",
      to: "qty",
      process: (value) => toNumber(value, 1),
    },
    { from: "internalNote", to: "internalNote" },
    { from: "shortDescription", to: "shortDescription" },
    { from: "description", to: "description" },
    {
      from: "ivProductRecId",
      to: "procurementNotes",
      process: (value, context) => {
        const custom = context.productCustomByIvProductId.get(value);
        return custom?.procurementNotes ?? null;
      },
    },
    {
      from: "ivProductRecId",
      to: "productNarrative",
      process: (value, context) => {
        const custom = context.productCustomByIvProductId.get(value);
        return custom?.productNarrative ?? null;
      },
    },
    {
      from: "sequenceNumber",
      to: "sequenceNumber",
      process: (value) => (value == null ? null : toInt(value, 0)),
    },
    {
      from: "unitPrice",
      to: "unitPrice",
      process: (value) => toNumber(value, 0),
    },
    {
      from: "unitCost",
      to: "unitCost",
      process: (value) => toNumber(value, 0),
    },
    {
      from: "listPrice",
      to: "listPrice",
      process: (value) => toNumber(value, 0),
    },
    {
      from: "discountAmount",
      to: "discount",
      process: (value) => toNumber(value, 0),
    },
    {
      from: "recurringRevenue",
      to: "recurringRevenue",
      process: (value) => toNumber(value, 0),
    },
    {
      from: "recurringCost",
      to: "recurringCost",
      process: (value) => toNumber(value, 0),
    },
    {
      from: "qtyPicked",
      to: "qtyPicked",
      process: (value) => toInt(value, 0),
    },
    {
      from: "qtyShipped",
      to: "qtyShipped",
      process: (value) => toInt(value, 0),
    },
    { from: "cancelReason", to: "cancelReason" },
    {
      from: "quantityCancelled",
      to: "cancelQty",
      process: (value) => (value == null ? null : toNumber(value, 0)),
    },
    { from: "billableFlag", to: "billableFlag" },
    { from: "taxableFlag", to: "taxableFlag" },
    { from: "invoiceFlag", to: "invoiceFlag" },
    { from: "recurringFlag", to: "recurringFlag" },
    { from: "poApprovedFlag", to: "poApprovedFlag" },
    { from: "calcPriceFlag", to: "calcPriceFlag" },
    { from: "calcCostFlag", to: "calcCostFlag" },
    { from: "cancelFlag", to: "cancelFlag" },
    {
      from: "catalogRecId",
      to: "catalogItemId",
      process: (value, context) => {
        if (!context.catalogItemIds.has(value)) {
          skipRow(
            `ProductData catalog item missing for catalogRecId ${value}`
          );
        }
        return value;
      },
    },
    {
      from: "ownerLevelRecId",
      to: "corporateLocationId",
      process: (value, context) => {
        if (!context.corporateLocationIds.has(value)) {
          skipRow(
            `ProductData corporate location missing for ownerLevelRecId ${value}`
          );
        }
        return value;
      },
    },
    {
      from: "srServiceRecId",
      to: "serviceTicketId",
      process: (value, context) => {
        if (value == null) return null;
        return context.serviceTicketIds.has(value) ? value : null;
      },
    },
    {
      from: "opportunityRecId",
      to: "opportunityId",
      process: (value, context) => {
        if (value == null) return null;
        return context.opportunityIds.has(value) ? value : null;
      },
    },
    { from: "updatedBy", to: "updatedById" },
    { from: "enteredBy", to: "createdById" },
    { from: "closedBy", to: "closedById" },
    {
      from: "cancelBy",
      to: "cancelById",
      process: (value, context) => {
        if (value == null) return "system";
        return context.usersByMemberRecId.get(value) ?? `cw-member:${value}`;
      },
    },
    { from: "dateClosedUtc", to: "closedAt" },
    { from: "cancelDateUtc", to: "cancelledAt" },
    {
      from: "dateEntered",
      to: "createdAt",
      process: (value) => value ?? new Date(0),
    },
    {
      from: "dateEnteredUtc",
      to: "createdAt",
      process: (value) => value ?? new Date(0),
    },
    {
      from: "lastUpdatedUTC",
      to: "updatedAt",
      process: (value) => value ?? new Date(0),
    },
  ],
};
