import type { JitSaleDetail, JitSaleListItem } from "@/types/jit-sale";

type DecimalLike = { toNumber(): number };

type SerializableJitSaleList = {
  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 SerializableJitSaleDetail = {
  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;
    qtyPlanned: DecimalLike;
    qtyActualSold: DecimalLike | null;
    malUnitPrice: DecimalLike;
    sellingPricePlanned: DecimalLike;
    sellingPriceActual: DecimalLike | null;
    agentNameSnapshot: string | null;
    agentSharePercent: DecimalLike | null;
    notes: string | null;
    grade: {
      id: bigint;
      code: string;
      name: string;
    };
    agent: {
      id: bigint;
      code: string;
      name: string;
    } | null;
    profitShareScheme: {
      id: bigint;
      code: string;
      name: string;
    } | null;
  }>;
};

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

export function serializeJitSaleListItem(sale: SerializableJitSaleList): JitSaleListItem {
  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 serializeJitSaleDetail(sale: SerializableJitSaleDetail): JitSaleDetail {
  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) => ({
      id: line.id.toString(),
      grade: {
        id: line.grade.id.toString(),
        code: line.grade.code,
        name: line.grade.name
      },
      qty_planned: line.qtyPlanned.toNumber(),
      qty_actual_sold: line.qtyActualSold?.toNumber() ?? null,
      mal_unit_price: line.malUnitPrice.toNumber(),
      selling_price_planned: line.sellingPricePlanned.toNumber(),
      selling_price_actual: line.sellingPriceActual?.toNumber() ?? null,
      agent: line.agent
        ? {
            id: line.agent.id.toString(),
            code: line.agent.code,
            name: line.agent.name
          }
        : null,
      profit_share_scheme: line.profitShareScheme
        ? {
            id: line.profitShareScheme.id.toString(),
            code: line.profitShareScheme.code,
            name: line.profitShareScheme.name
          }
        : null,
      agent_name: line.agentNameSnapshot,
      agent_share_percent: line.agentSharePercent?.toNumber() ?? null,
      notes: line.notes
    }))
  };
}
