import type {
  RegularSaleCandidateLot,
  RegularSaleDetail,
  RegularSaleListItem
} from "@/types/regular-sale";

type DecimalLike = {
  toNumber(): number;
};

type SerializableRegularSaleCandidateLot = {
  id: bigint;
  lotCode: string;
  availableQty: DecimalLike;
  unitCost: DecimalLike;
  grade: { name: string } | null;
  unit: { code: string };
  warehouse: { name: string };
  warehouseLocation: { name: string } | null;
  purchase: {
    agent: { name: string } | null;
    profitShareScheme: { shareAgent: DecimalLike } | null;
  } | null;
  purchaseLine: {
    malUnitPrice: DecimalLike | null;
  } | null;
};

type SerializableRegularSaleList = {
  id: bigint;
  saleNo: string;
  saleDate: Date;
  buyerCurrencyCode: string;
  companyCurrencyCode: string;
  exchangeRate: DecimalLike | null;
  totalNominalBuyer: DecimalLike;
  totalNominalCompany: DecimalLike;
  totalAgentCommission: DecimalLike;
  status: string;
  buyer: {
    id: bigint;
    code: string;
    name: string;
  };
  lines: Array<{ id: bigint }>;
};

type SerializableRegularSaleDetail = {
  id: bigint;
  saleNo: string;
  saleDate: Date;
  closeDate: Date | null;
  buyerCurrencyCode: string;
  companyCurrencyCode: string;
  exchangeRate: DecimalLike | null;
  shippingCostBuyer: DecimalLike;
  shippingCostCompany: DecimalLike;
  shippingReceiptFileUrl: string | null;
  totalNominalBuyer: DecimalLike;
  totalNominalCompany: DecimalLike;
  totalAgentCommission: DecimalLike;
  status: string;
  notes: string | null;
  createdAt: Date;
  buyer: {
    id: bigint;
    code: string;
    name: string;
  };
  courier: {
    id: bigint;
    code: string;
    name: string;
  } | null;
  lines: Array<{
    id: bigint;
    availableQtySnapshot: DecimalLike;
    malUnitPriceSnapshot: DecimalLike | null;
    agentNameSnapshot: string | null;
    agentSharePercent: DecimalLike | null;
    qtyPlanned: DecimalLike;
    sellingPricePlanned: DecimalLike;
    qtyActualSold: DecimalLike | null;
    qtyReturned: DecimalLike | null;
    qtyShrinkage: DecimalLike | null;
    sellingPriceActual: DecimalLike | null;
    notes: string | null;
    lot: {
      id: bigint;
      lotCode: string;
      availableQty: DecimalLike;
      unitCost: DecimalLike;
      grade: { name: string } | null;
      unit: { code: string };
      warehouse: { name: string };
      warehouseLocation: { name: string } | null;
    };
  }>;
};

function serializeDate(value: Date | null) {
  return value ? value.toISOString().slice(0, 10) : null;
}

export function serializeRegularSaleCandidateLot(
  lot: SerializableRegularSaleCandidateLot
): RegularSaleCandidateLot {
  return {
    lot_id: lot.id.toString(),
    lot_code: lot.lotCode,
    grade: lot.grade?.name ?? "-",
    unit_code: lot.unit.code,
    warehouse: lot.warehouse.name,
    location: lot.warehouseLocation?.name ?? null,
    available_qty: lot.availableQty.toNumber(),
    unit_cost: lot.unitCost.toNumber(),
    mal_unit_price: lot.purchaseLine?.malUnitPrice?.toNumber() ?? null,
    agent_name: lot.purchase?.agent?.name ?? null,
    agent_share_percent: lot.purchase?.profitShareScheme?.shareAgent.toNumber() ?? null
  };
}

export function serializeRegularSaleListItem(
  sale: SerializableRegularSaleList
): RegularSaleListItem {
  return {
    id: sale.id.toString(),
    sale_no: sale.saleNo,
    sale_date: sale.saleDate.toISOString().slice(0, 10),
    buyer: {
      id: sale.buyer.id.toString(),
      code: sale.buyer.code,
      name: sale.buyer.name
    },
    buyer_currency_code: sale.buyerCurrencyCode,
    company_currency_code: sale.companyCurrencyCode,
    exchange_rate: sale.exchangeRate?.toNumber() ?? null,
    status: sale.status,
    item_count: sale.lines.length,
    total_nominal_buyer: sale.totalNominalBuyer.toNumber(),
    total_nominal_company: sale.totalNominalCompany.toNumber(),
    total_agent_commission: sale.totalAgentCommission.toNumber()
  };
}

export function serializeRegularSaleDetail(
  sale: SerializableRegularSaleDetail
): RegularSaleDetail {
  return {
    id: sale.id.toString(),
    sale_no: sale.saleNo,
    sale_date: sale.saleDate.toISOString().slice(0, 10),
    close_date: serializeDate(sale.closeDate),
    buyer: {
      id: sale.buyer.id.toString(),
      code: sale.buyer.code,
      name: sale.buyer.name
    },
    courier: sale.courier
      ? {
          id: sale.courier.id.toString(),
          code: sale.courier.code,
          name: sale.courier.name
        }
      : null,
    buyer_currency_code: sale.buyerCurrencyCode,
    company_currency_code: sale.companyCurrencyCode,
    exchange_rate: sale.exchangeRate?.toNumber() ?? null,
    shipping_cost_buyer: sale.shippingCostBuyer.toNumber(),
    shipping_cost_company: sale.shippingCostCompany.toNumber(),
    shipping_receipt_file_url: sale.shippingReceiptFileUrl,
    total_nominal_buyer: sale.totalNominalBuyer.toNumber(),
    total_nominal_company: sale.totalNominalCompany.toNumber(),
    total_agent_commission: sale.totalAgentCommission.toNumber(),
    status: sale.status,
    notes: sale.notes,
    created_at: sale.createdAt.toISOString(),
    lines: sale.lines.map((line) => {
      return {
        id: line.id.toString(),
        lot_id: line.lot.id.toString(),
        lot_code: line.lot.lotCode,
        grade: line.lot.grade?.name ?? "-",
        unit_code: line.lot.unit.code,
        warehouse: line.lot.warehouse.name,
        location: line.lot.warehouseLocation?.name ?? null,
        available_qty_snapshot: line.availableQtySnapshot.toNumber(),
        current_available_qty: line.lot.availableQty.toNumber(),
        mal_unit_price_snapshot: line.malUnitPriceSnapshot?.toNumber() ?? null,
        unit_cost: line.lot.unitCost.toNumber(),
        agent_name: line.agentNameSnapshot,
        agent_share_percent: line.agentSharePercent?.toNumber() ?? null,
        qty_planned: line.qtyPlanned.toNumber(),
        selling_price_planned: line.sellingPricePlanned.toNumber(),
        qty_actual_sold: line.qtyActualSold?.toNumber() ?? null,
        qty_returned: line.qtyReturned?.toNumber() ?? null,
        qty_shrinkage: line.qtyShrinkage?.toNumber() ?? null,
        selling_price_actual: line.sellingPriceActual?.toNumber() ?? null,
        notes: line.notes
      };
    })
  };
}
