import type {
  PurchaseRealizationDetail,
  PurchaseRealizationListItem
} from "@/types/purchase-realization";

type DecimalLike = { toNumber(): number };

type SerializablePurchaseRealization = {
  id: bigint;
  purchaseNo: string;
  purchaseType: string;
  purchaseDate: Date;
  status: string;
  agent: { name: string } | null;
  buyoutSourceAgent: { name: string } | null;
  profitShareScheme: {
    name: string;
    shareAgent: DecimalLike;
  } | null;
  realizationSummary: {
    status: string;
    qtyOpening: DecimalLike;
    qtyRemaining: DecimalLike;
    qtySold: DecimalLike;
    qtyReturned: DecimalLike;
    qtyShrinkage: DecimalLike;
    costOpeningTotal: DecimalLike;
    costAdditionalTotal: DecimalLike;
    revenueTotal: DecimalLike;
    profitLossTotal: DecimalLike;
    agentSharePercent: DecimalLike | null;
    agentProfitTotal: DecimalLike;
    closedAt: Date | null;
  } | null;
  realizationEntries?: Array<{
    id: bigint;
    eventType: string;
    referenceType: string;
    referenceId: bigint | null;
    occurredAt: Date;
    qtyIn: DecimalLike;
    qtyOut: DecimalLike;
    qtyShrinkage: DecimalLike;
    amountCost: DecimalLike;
    amountRevenue: DecimalLike;
    amountExpense: DecimalLike;
    amountProfit: DecimalLike;
    agentAmount: DecimalLike;
    notes: string | null;
    lot: {
      id: bigint;
      lotCode: string;
    } | null;
  }>;
};

function summaryOrZero(summary: SerializablePurchaseRealization["realizationSummary"]) {
  return {
    status: summary?.status ?? "OPEN",
    qty_opening: summary?.qtyOpening.toNumber() ?? 0,
    qty_remaining: summary?.qtyRemaining.toNumber() ?? 0,
    qty_sold: summary?.qtySold.toNumber() ?? 0,
    qty_returned: summary?.qtyReturned.toNumber() ?? 0,
    qty_shrinkage: summary?.qtyShrinkage.toNumber() ?? 0,
    cost_opening_total: summary?.costOpeningTotal.toNumber() ?? 0,
    cost_additional_total: summary?.costAdditionalTotal.toNumber() ?? 0,
    revenue_total: summary?.revenueTotal.toNumber() ?? 0,
    profit_loss_total: summary?.profitLossTotal.toNumber() ?? 0,
    agent_share_percent: summary?.agentSharePercent?.toNumber() ?? null,
    agent_profit_total: summary?.agentProfitTotal.toNumber() ?? 0,
    closed_at: summary?.closedAt?.toISOString() ?? null
  };
}

function resolveSupplierName(item: SerializablePurchaseRealization) {
  return item.agent?.name ?? item.buyoutSourceAgent?.name ?? "-";
}

export function serializePurchaseRealizationListItem(
  purchase: SerializablePurchaseRealization
): PurchaseRealizationListItem {
  const summary = summaryOrZero(purchase.realizationSummary);

  return {
    purchase_id: purchase.id.toString(),
    purchase_no: purchase.purchaseNo,
    purchase_type: purchase.purchaseType,
    purchase_date: purchase.purchaseDate.toISOString().slice(0, 10),
    supplier_name: resolveSupplierName(purchase),
    status: summary.status,
    qty_opening: summary.qty_opening,
    qty_remaining: summary.qty_remaining,
    qty_sold: summary.qty_sold,
    qty_shrinkage: summary.qty_shrinkage,
    revenue_total: summary.revenue_total,
    profit_loss_total: summary.profit_loss_total,
    agent_profit_total: summary.agent_profit_total
  };
}

export function serializePurchaseRealizationDetail(
  purchase: SerializablePurchaseRealization
): PurchaseRealizationDetail {
  const summary = summaryOrZero(purchase.realizationSummary);

  return {
    purchase: {
      id: purchase.id.toString(),
      purchase_no: purchase.purchaseNo,
      purchase_type: purchase.purchaseType,
      purchase_date: purchase.purchaseDate.toISOString().slice(0, 10),
      supplier_name: resolveSupplierName(purchase),
      status: purchase.status,
      agent_name: purchase.agent?.name ?? null,
      buyout_source_agent_name: purchase.buyoutSourceAgent?.name ?? null,
      profit_share_scheme_name: purchase.profitShareScheme?.name ?? null,
      share_agent_percent: purchase.profitShareScheme?.shareAgent.toNumber() ?? null
    },
    summary,
    entries: (purchase.realizationEntries ?? []).map((entry) => ({
      id: entry.id.toString(),
      event_type: entry.eventType,
      reference_type: entry.referenceType,
      reference_id: entry.referenceId?.toString() ?? null,
      lot_id: entry.lot?.id.toString() ?? null,
      lot_code: entry.lot?.lotCode ?? null,
      occurred_at: entry.occurredAt.toISOString(),
      qty_in: entry.qtyIn.toNumber(),
      qty_out: entry.qtyOut.toNumber(),
      qty_shrinkage: entry.qtyShrinkage.toNumber(),
      amount_cost: entry.amountCost.toNumber(),
      amount_revenue: entry.amountRevenue.toNumber(),
      amount_expense: entry.amountExpense.toNumber(),
      amount_profit: entry.amountProfit.toNumber(),
      agent_amount: entry.agentAmount.toNumber(),
      notes: entry.notes
    }))
  };
}
