import type { PurchaseDetail, PurchaseListItem } from "@/types/purchase";

type DecimalLike = { toNumber(): number };

type PurchaseListSerializable = {
  id: bigint;
  purchaseNo: string;
  purchaseDate: Date;
  status: string;
  receivedAt: Date | null;
  agent: { id: bigint; name: string } | null;
  lines: Array<{ subtotal: DecimalLike }>;
  _count?: {
    receipts: number;
    lots: number;
  };
};

type PurchaseDetailSerializable = {
  id: bigint;
  purchaseNo: string;
  purchaseDate: Date;
  supplierInvoiceNo: string | null;
  status: string;
  notes: string | null;
  receivedAt: Date | null;
  receivedByEmployee: { id: bigint; name: string } | null;
  agent: { id: bigint; name: string } | null;
  profitShareScheme: { id: bigint; name: string } | null;
  courier: { id: bigint; name: string } | null;
  moistureBuyPercent: DecimalLike | null;
  moistureReceivedPercent: DecimalLike | null;
  aboveAverageRatioPercent: DecimalLike | null;
  mkSharePercent: DecimalLike | null;
  nonMkSharePercent: DecimalLike | null;
  shippingCost: DecimalLike | null;
  incomingOperationalCost: DecimalLike | null;
  afterArrivalOperationalCost: DecimalLike | null;
  analysis: {
    id: bigint;
    status: string;
    weightBuy: DecimalLike | null;
    weightReceived: DecimalLike | null;
    weightFinal: DecimalLike | null;
    averagePrice: DecimalLike | null;
    modalBeli: DecimalLike | null;
    modalMasuk: DecimalLike | null;
    modalJual: DecimalLike | null;
    modalBarang: DecimalLike | null;
    totalModalBeli: DecimalLike | null;
    totalModalMal: DecimalLike | null;
    marketReferencePrice: DecimalLike | null;
    costEntries: Array<{
      id: bigint;
      costType: string;
      description: string | null;
      amount: DecimalLike;
      proofFileUrl?: string | null;
    }>;
  } | null;
  lines: Array<{
    id: bigint;
    qtyOrdered: DecimalLike;
    qtyReceived: DecimalLike;
    qtyAccepted: DecimalLike;
    qtyRejected: DecimalLike;
    purchaseMoisturePercent: DecimalLike | null;
    moistureReceivedPercent: DecimalLike | null;
    unitCost: DecimalLike;
    malUnitPrice: DecimalLike | null;
    unitPrice: DecimalLike;
    subtotal: DecimalLike;
    classificationStatus: string;
    notes: string | null;
    warehouse: { id: bigint; code: string; name: string } | null;
    warehouseLocation: { id: bigint; code: string; name: string } | null;
    grade: { id: bigint; name: string } | null;
    unit: { id: bigint; code: string };
  }>;
};

function toOptionalNumber(value: DecimalLike | null) {
  return value ? value.toNumber() : null;
}

export function serializePurchaseListItem(purchase: PurchaseListSerializable): PurchaseListItem {
  return {
    id: purchase.id.toString(),
    purchase_no: purchase.purchaseNo,
    purchase_date: purchase.purchaseDate.toISOString().slice(0, 10),
    received_at: purchase.receivedAt ? purchase.receivedAt.toISOString() : null,
    agent: purchase.agent
      ? {
          id: purchase.agent.id.toString(),
          name: purchase.agent.name
        }
      : null,
    status: purchase.status,
    line_count: purchase.lines.length,
    receipt_count: purchase._count?.receipts ?? 0,
    lot_count: purchase._count?.lots ?? 0,
    grand_total: purchase.lines.reduce((sum, line) => sum + line.subtotal.toNumber(), 0)
  };
}

export function serializePurchaseDetail(purchase: PurchaseDetailSerializable): PurchaseDetail {
  return {
    id: purchase.id.toString(),
    purchase_no: purchase.purchaseNo,
    purchase_date: purchase.purchaseDate.toISOString().slice(0, 10),
    supplier_invoice_no: purchase.supplierInvoiceNo,
    status: purchase.status,
    notes: purchase.notes,
    received_at: purchase.receivedAt ? purchase.receivedAt.toISOString() : null,
    received_by_employee: purchase.receivedByEmployee
      ? {
          id: purchase.receivedByEmployee.id.toString(),
          name: purchase.receivedByEmployee.name
        }
      : null,
    agent: purchase.agent ? { id: purchase.agent.id.toString(), name: purchase.agent.name } : null,
    profit_share_scheme: purchase.profitShareScheme
      ? {
          id: purchase.profitShareScheme.id.toString(),
          name: purchase.profitShareScheme.name
        }
      : null,
    courier: purchase.courier ? { id: purchase.courier.id.toString(), name: purchase.courier.name } : null,
    moisture_buy_percent: toOptionalNumber(purchase.moistureBuyPercent),
    moisture_received_percent: toOptionalNumber(purchase.moistureReceivedPercent),
    above_average_ratio_percent: toOptionalNumber(purchase.aboveAverageRatioPercent),
    mk_share_percent: toOptionalNumber(purchase.mkSharePercent),
    non_mk_share_percent: toOptionalNumber(purchase.nonMkSharePercent),
    shipping_cost: toOptionalNumber(purchase.shippingCost),
    incoming_operational_cost: toOptionalNumber(purchase.incomingOperationalCost),
    after_arrival_operational_cost: toOptionalNumber(purchase.afterArrivalOperationalCost),
    analysis: purchase.analysis
        ? {
          id: purchase.analysis.id.toString(),
          status: purchase.analysis.status,
          weight_buy: toOptionalNumber(purchase.analysis.weightBuy),
          weight_received: toOptionalNumber(purchase.analysis.weightReceived),
          weight_final: toOptionalNumber(purchase.analysis.weightFinal),
          average_price: toOptionalNumber(purchase.analysis.averagePrice),
          modal_beli: toOptionalNumber(purchase.analysis.modalBeli),
          modal_masuk: toOptionalNumber(purchase.analysis.modalMasuk),
          modal_jual: toOptionalNumber(purchase.analysis.modalJual),
          modal_barang: toOptionalNumber(purchase.analysis.modalBarang),
          total_modal_beli: toOptionalNumber(purchase.analysis.totalModalBeli),
          total_modal_mal: toOptionalNumber(purchase.analysis.totalModalMal),
          market_reference_price: toOptionalNumber(purchase.analysis.marketReferencePrice),
          cost_lines: (purchase.analysis.costEntries ?? []).map((costEntry) => ({
            id: costEntry.id.toString(),
            cost_name: costEntry.costType,
            amount: costEntry.amount.toNumber(),
            notes: costEntry.description,
            proof_file_url: costEntry.proofFileUrl ?? null
          }))
        }
      : null,
    lines: purchase.lines.map((line) => ({
      id: line.id.toString(),
      grade: line.grade
        ? { id: line.grade.id.toString(), name: line.grade.name }
        : null,
      qty_ordered: line.qtyOrdered.toNumber(),
      qty_received: line.qtyReceived.toNumber(),
      qty_accepted: line.qtyAccepted.toNumber(),
      qty_rejected: line.qtyRejected.toNumber(),
      purchase_moisture_percent: toOptionalNumber(line.purchaseMoisturePercent),
      moisture_received_percent: toOptionalNumber(line.moistureReceivedPercent),
      unit_cost: line.unitCost.toNumber(),
      mal_unit_price: toOptionalNumber(line.malUnitPrice),
      unit: { id: line.unit.id.toString(), code: line.unit.code },
      unit_price: line.unitPrice.toNumber(),
      subtotal: line.subtotal.toNumber(),
      classification_status: line.classificationStatus,
      warehouse: line.warehouse
        ? { id: line.warehouse.id.toString(), code: line.warehouse.code, name: line.warehouse.name }
        : null,
      warehouse_location: line.warehouseLocation
        ? {
            id: line.warehouseLocation.id.toString(),
            code: line.warehouseLocation.code,
            name: line.warehouseLocation.name
          }
        : null,
      notes: line.notes
    }))
  };
}
