/**
 * 提车应收款 ↔ 租赁合同 原型联动与应收计算
 * 应收口径：按提车日与合同 2.1.2 / 2.1.3 自动生成（见 pickup-receivable-calc.js）
 */

import {
  buildVehiclePickupSchedule,
  buildBatchPickupScheduleSummary,
  describePickupRule,
} from './pickup-receivable-calc.js';

export {
  buildVehiclePickupSchedule,
  buildBatchPickupScheduleSummary,
  describePickupRule,
} from './pickup-receivable-calc.js';

export const PICKUP_RECEIVABLE_STORAGE_KEY = 'oneos.pickup-receivable.list.v6';

var LEGACY_PICKUP_STORAGE_KEYS = [
  'oneos.pickup-receivable.list.v5',
  'oneos.pickup-receivable.list.v4',
  'oneos.pickup-receivable.list.v3',
  'oneos.pickup-receivable.list.v2',
  'oneos.pickup-receivable.list.v1',
];

function isPlaceholderField(value) {
  var s = String(value == null ? '' : value).trim();
  return !s || s === '—' || s === '-' || s === '--';
}

function pickupRecordRichness(record) {
  if (!record) return -1;
  var score = 0;
  if (!isPlaceholderField(record.customerName)) score += 4;
  if (!isPlaceholderField(record.projectName)) score += 3;
  if (!isPlaceholderField(record.businessDept)) score += 1;
  if (!isPlaceholderField(record.businessPerson)) score += 1;
  score += (record.leaseOrderVehicles || []).length;
  score += (record.children || []).length;
  return score;
}

/** 主表行必须含合同编号及客户/项目名称，否则视为脏数据丢弃 */
export function isValidPickupMainRecord(record) {
  if (!record || typeof record !== 'object') return false;
  var code = String(record.contractCode || '').trim();
  if (!code) return false;
  var hasMeta = !isPlaceholderField(record.customerName) && !isPlaceholderField(record.projectName);
  if (!hasMeta) return false;
  var vehicleCount = (record.leaseOrderVehicles || []).length;
  var declaredCount = parseInt(record.contractVehicleCount, 10);
  if (vehicleCount <= 0 && (Number.isNaN(declaredCount) || declaredCount <= 0)) return false;
  return true;
}

export function dedupePickupListByContractCode(list) {
  var bestByCode = {};
  (list || []).forEach(function (row) {
    if (!isValidPickupMainRecord(row)) return;
    var code = String(row.contractCode || '').trim();
    var prev = bestByCode[code];
    if (!prev || pickupRecordRichness(row) > pickupRecordRichness(prev)) {
      bestByCode[code] = row;
    }
  });
  return Object.keys(bestByCode)
    .sort()
    .map(function (code) {
      return bestByCode[code];
    });
}

export function pickSeedIdentityFields(seedRow) {
  return {
    contractCode: seedRow.contractCode,
    contractType: seedRow.contractType,
    projectName: seedRow.projectName,
    customerName: seedRow.customerName,
    businessDept: seedRow.businessDept,
    businessPerson: seedRow.businessPerson,
    contractEffectiveDate: seedRow.contractEffectiveDate,
    contractApprovalStatus: seedRow.contractApprovalStatus,
    contractStatus: seedRow.contractStatus,
    paymentCycleMonths: seedRow.paymentCycleMonths,
    paymentMethod: seedRow.paymentMethod,
    deliveryDate: seedRow.deliveryDate,
    deliveryDateTbd: seedRow.deliveryDateTbd,
    deliveryRegion: seedRow.deliveryRegion,
    leaseOrderVehicles: seedRow.leaseOrderVehicles,
    contractVehicleCount: seedRow.contractVehicleCount,
    createdFromLeaseSubmit: seedRow.createdFromLeaseSubmit,
    leaseSubmitAt: seedRow.leaseSubmitAt,
    handleDemo: seedRow.handleDemo,
  };
}

/** 仅保留办理提交后生成的子单，丢弃旧版 mock 审批流数据 */
export function sanitizeStoredChildren(children) {
  return (children || []).filter(function (child) {
    return String(child.auditStatus || '').trim() === '已生成';
  });
}

export function parsePaymentCycleMonths(feeInfoOrPeriod) {
  if (feeInfoOrPeriod == null) return 1;
  if (typeof feeInfoOrPeriod === 'number') return feeInfoOrPeriod || 1;
  if (typeof feeInfoOrPeriod === 'object' && feeInfoOrPeriod.paymentPeriod != null) {
    return Number(feeInfoOrPeriod.paymentPeriod) || 1;
  }
  var legacy = { '1个月': 1, '3个月': 3, '6个月': 6, '12个月': 12 };
  return legacy[feeInfoOrPeriod] || 1;
}

export function sumServiceFee(row) {
  if (row == null) return 0;
  if (typeof row.serviceFee === 'number') return row.serviceFee;
  if (row.serviceFee != null && row.serviceFee !== '') return parseFloat(row.serviceFee) || 0;
  var extra = row.extraServices || row.serviceItems || [];
  return extra.reduce(function (sum, item) {
    var fee = item.fee != null ? item.fee : item.receivable;
    return sum + (parseFloat(fee) || 0);
  }, 0);
}

/** 将租赁订单行展开为单车明细（原型）；每行按车型数量或实际车牌展开 */
export function expandLeaseOrderToVehicles(leaseOrder, paymentCycleMonths) {
  var months = paymentCycleMonths || 1;
  var rows = (leaseOrder && leaseOrder.rows) || [];
  var vehicles = [];
  var seq = 0;

  rows.forEach(function (row) {
    var brandModels = row.brandModels || (row.brandModel ? [row.brandModel] : []);
    if (!brandModels.length && row.brand && row.model) {
      brandModels = [[row.brand, row.model]];
    }
    var pair = brandModels[0] || ['', ''];
    var plateNos = row.plateNos || (row.plateNo ? [row.plateNo] : ['']);
    var monthRent = parseFloat(row.rent != null ? row.rent : row.monthRent) || 0;
    var deposit = parseFloat(row.deposit) || 0;
    var serviceFeeTotal = sumServiceFee(row);
    var actualPlates = plateNos.filter(function (plate) {
      return plate && plate !== '以实际交付为准';
    });
    var qty = actualPlates.length > 0
      ? actualPlates.length
      : Math.max(1, parseInt(row.vehicleQty, 10) || 1);

    for (var i = 0; i < qty; i += 1) {
      seq += 1;
      var modelPair = brandModels[i] || pair;
      var plate = actualPlates[i] || actualPlates[0] || '';
      vehicles.push({
        key: 'lv-' + seq,
        seq: seq,
        brand: modelPair[0] || row.brand || '',
        model: modelPair[1] || row.model || '',
        plateNo: plate,
        monthRent: monthRent,
        deposit: deposit,
        serviceFeeTotal: serviceFeeTotal,
      });
    }
  });

  return vehicles;
}

/** 从租赁合同列表 vehicles 字段构建（无订单行时兜底） */
export function vehiclesFromLeaseListRecord(record, paymentCycleMonths) {
  var list = (record && record.vehicles) || [];
  if (!list.length) return [];
  return list.map(function (v, index) {
    var monthRent = parseFloat(v.monthRent || v.rent) || 5000;
    var deposit = parseFloat(v.deposit) || 10000;
    var serviceFeeTotal = sumServiceFee(v) || 500;
    return {
      key: 'lv-' + (index + 1),
      seq: index + 1,
      brand: v.brand || '',
      model: v.model || '',
      plateNo: v.plateNo && v.plateNo !== '-' ? v.plateNo : '',
      monthRent: monthRent,
      deposit: deposit,
      serviceFeeTotal: serviceFeeTotal,
    };
  });
}

function calcVehicleTotalFromSchedule(vehicle, pickupDate, paymentCycleMonths) {
  var schedule = buildVehiclePickupSchedule({
    monthRent: vehicle.monthRent,
    monthServiceFee: vehicle.serviceFeeTotal,
    deposit: vehicle.deposit,
    pickupDate: pickupDate,
    paymentCycleMonths: paymentCycleMonths,
  });
  if (!schedule) {
    return roundFallbackVehicleTotal(vehicle, paymentCycleMonths);
  }
  return schedule.totalReceivable;
}

function roundFallbackVehicleTotal(vehicle, paymentCycleMonths) {
  var months = paymentCycleMonths || 1;
  var monthRent = parseFloat(vehicle.monthRent) || 0;
  var deposit = parseFloat(vehicle.deposit) || 0;
  var service = parseFloat(vehicle.serviceFeeTotal) || 0;
  return Math.round((monthRent * months + deposit + service) * 100) / 100;
}

/** @deprecated 保留兼容；有提车日时请用 buildVehiclePickupSchedule */
export function calcVehicleReceivableAmount(vehicle, paymentCycleMonths, pickupDate) {
  if (pickupDate) {
    return calcVehicleTotalFromSchedule(vehicle, pickupDate, paymentCycleMonths);
  }
  return roundFallbackVehicleTotal(vehicle, paymentCycleMonths);
}

export function calcContractReceivableTotal(leaseOrderVehicles, paymentCycleMonths, pickupDate) {
  return (leaseOrderVehicles || []).reduce(function (sum, v) {
    return sum + calcVehicleReceivableAmount(v, paymentCycleMonths, pickupDate || v.pickupDate);
  }, 0);
}

function calcVehicleReceivableBreakdown(vehicle, paymentCycleMonths, pickupDate) {
  var date = pickupDate || vehicle.pickupDate;
  if (date) {
    var schedule = buildVehiclePickupSchedule({
      monthRent: vehicle.monthRent,
      monthServiceFee: vehicle.serviceFeeTotal,
      deposit: vehicle.deposit,
      pickupDate: date,
      paymentCycleMonths: paymentCycleMonths,
    });
    if (schedule) {
      return schedule.items.reduce(function (acc, item) {
        acc.rent += item.rent || 0;
        acc.deposit += item.deposit || 0;
        acc.service += item.service || 0;
        return acc;
      }, { rent: 0, deposit: 0, service: 0 });
    }
  }
  var months = paymentCycleMonths || 1;
  var monthRent = parseFloat(vehicle.monthRent) || 0;
  var deposit = parseFloat(vehicle.deposit) || 0;
  var service = parseFloat(vehicle.serviceFeeTotal) || 0;
  return {
    rent: Math.round(monthRent * months * 100) / 100,
    deposit: deposit,
    service: service,
  };
}

export function calcContractReceivableBreakdown(leaseOrderVehicles, paymentCycleMonths, pickupDate) {
  return (leaseOrderVehicles || []).reduce(function (acc, v) {
    var part = calcVehicleReceivableBreakdown(v, paymentCycleMonths, pickupDate || v.pickupDate);
    acc.rent += part.rent;
    acc.deposit += part.deposit;
    acc.service += part.service;
    return acc;
  }, { rent: 0, deposit: 0, service: 0 });
}

function breakdownFromBatchSummary(schedule) {
  if (!schedule) return { rent: 0, deposit: 0, service: 0 };
  var before = schedule.beforePickup || {};
  var month25 = schedule.month25 || {};
  return {
    rent: (before.rent || 0) + (month25.rent || 0),
    deposit: before.deposit || 0,
    service: (before.service || 0) + (month25.service || 0),
  };
}

export function calcReceivedBreakdown(children) {
  return (children || []).reduce(function (acc, child) {
    var status = String(child.auditStatus || '');
    if (status !== '审批通过' && status !== '已生成') return acc;

    var receivedTotal = parseFloat(
      child.financeReceived != null ? child.financeReceived : child.actualTotal,
    ) || 0;
    if (receivedTotal <= 0) return acc;

    if (child.receivedRent != null || child.receivedDeposit != null || child.receivedService != null) {
      acc.rent += parseFloat(child.receivedRent) || 0;
      acc.deposit += parseFloat(child.receivedDeposit) || 0;
      acc.service += parseFloat(child.receivedService) || 0;
      return acc;
    }

    var receivablePart = breakdownFromBatchSummary(child.receivableSchedule);
    var receivableTotal = receivablePart.rent + receivablePart.deposit + receivablePart.service;
    if (receivableTotal > 0) {
      var ratio = receivedTotal / receivableTotal;
      acc.rent += receivablePart.rent * ratio;
      acc.deposit += receivablePart.deposit * ratio;
      acc.service += receivablePart.service * ratio;
    } else {
      acc.rent += receivedTotal;
    }
    return acc;
  }, { rent: 0, deposit: 0, service: 0 });
}

export function vehicleMatchKey(v) {
  return [v.brand || '', v.model || '', v.plateNo || '', String(v.seq || '')].join('|');
}

export function collectPickedVehicleKeys(children) {
  var keys = new Set();
  (children || []).forEach(function (child) {
    var audit = String(child.auditStatus || '');
    if (audit === '已驳回' || audit === '审批驳回') return;
    (child.deliveryVehicles || []).forEach(function (v) {
      keys.add(vehicleMatchKey(v));
    });
  });
  return keys;
}

export function countPickedUpVehicles(record) {
  return collectPickedVehicleKeys(record.children).size;
}

export function calcReceivedTotal(children) {
  return (children || []).reduce(function (sum, child) {
    var status = String(child.auditStatus || '');
    if (status !== '审批通过' && status !== '已生成') return sum;
    var n = parseFloat(child.financeReceived != null ? child.financeReceived : child.actualTotal);
    return sum + (Number.isNaN(n) ? 0 : n);
  }, 0);
}

export function shouldShowRefund(record) {
  var approval = String(record.contractApprovalStatus || record.leaseApprovalStatus || '');
  var status = String(record.contractStatus || '');
  return approval === '审批驳回' || status === '已终止' || status === '已结束';
}

/** 子表批次操作：租赁合同审批驳回时可退款 */
export function shouldShowSubBatchRefund(record) {
  var approval = String(record.contractApprovalStatus || record.leaseApprovalStatus || '').trim();
  return approval === '审批驳回' || approval === '已驳回';
}

export function formatDeliveryLocation(record, overrideLocation) {
  if (overrideLocation) return overrideLocation;
  if (record && record.deliveryLocation) return record.deliveryLocation;
  if (record && record.deliveryRegion && record.deliveryRegion.length) {
    return record.deliveryRegion.join('');
  }
  return '—';
}

export function canShowHandle(record) {
  if (record.allVehiclesReceivableCompleted) return false;
  var total = record.contractVehicleCount || (record.leaseOrderVehicles || []).length;
  var picked = countPickedUpVehicles(record);
  return picked < total;
}

function enrichChildDeliveryVehicles(child, parent) {
  if (!child) return child;
  var months = parent.paymentCycleMonths || 1;
  var pickupDate = child.pickupDate || '';
  var batchLocation = child.deliveryLocation || formatDeliveryLocation(parent);
  child.deliveryLocation = batchLocation;

  var vehicles = (child.deliveryVehicles || []).map(function (v) {
    var enriched = Object.assign({}, v);
    enriched.deliveryTime = enriched.deliveryTime || pickupDate || '—';
    enriched.deliveryLocation = enriched.deliveryLocation || batchLocation;

    if (enriched.receivableTotal == null && pickupDate) {
      var leaseV = (parent.leaseOrderVehicles || []).find(function (lv) {
        return lv.seq === v.seq || (lv.plateNo && lv.plateNo === v.plateNo);
      });
      if (leaseV) {
        var schedule = buildVehiclePickupSchedule({
          monthRent: leaseV.monthRent,
          monthServiceFee: leaseV.serviceFeeTotal,
          deposit: leaseV.deposit,
          pickupDate: pickupDate,
          paymentCycleMonths: months,
        });
        if (schedule) {
          var pre = schedule.items[0] || {};
          var post = schedule.items[1] || {};
          enriched.receivableRent = (pre.rent || 0) + (post.rent || 0);
          enriched.receivableDeposit = pre.deposit || 0;
          enriched.receivableService = (pre.service || 0) + (post.service || 0);
          enriched.receivableTotal = (pre.amount || 0) + (post.amount || 0);
        }
      }
    }

    enriched.receivableRent = enriched.receivableRent != null ? enriched.receivableRent : 0;
    enriched.receivableDeposit = enriched.receivableDeposit != null ? enriched.receivableDeposit : 0;
    enriched.receivableService = enriched.receivableService != null ? enriched.receivableService : 0;
    enriched.receivableTotal = enriched.receivableTotal != null
      ? enriched.receivableTotal
      : enriched.receivableRent + enriched.receivableDeposit + enriched.receivableService;
    return enriched;
  });

  var recvTotal = parseFloat(child.financeReceived != null ? child.financeReceived : child.actualTotal) || 0;
  var batchReceivable = parseFloat(child.receivableTotal) || vehicles.reduce(function (sum, v) {
    return sum + (parseFloat(v.receivableTotal) || 0);
  }, 0);
  var ratio = batchReceivable > 0 ? recvTotal / batchReceivable : 0;
  var hasVehicleReceived = vehicles.some(function (v) {
    return v.receivedTotal != null || v.receivedRent != null;
  });

  if (recvTotal > 0 && !hasVehicleReceived) {
    var batchRent = parseFloat(child.receivedRent);
    var batchDeposit = parseFloat(child.receivedDeposit);
    var batchService = parseFloat(child.receivedService);
    var useBatchSplit = !Number.isNaN(batchRent) && batchRent > 0;
    vehicles = vehicles.map(function (v) {
      var next = Object.assign({}, v);
      if (useBatchSplit && batchReceivable > 0) {
        var share = (parseFloat(v.receivableTotal) || 0) / batchReceivable;
        next.receivedRent = Math.round((batchRent || 0) * share * 100) / 100;
        next.receivedDeposit = Math.round((batchDeposit || 0) * share * 100) / 100;
        next.receivedService = Math.round((batchService || 0) * share * 100) / 100;
      } else {
        next.receivedRent = Math.round((v.receivableRent || 0) * ratio * 100) / 100;
        next.receivedDeposit = Math.round((v.receivableDeposit || 0) * ratio * 100) / 100;
        next.receivedService = Math.round((v.receivableService || 0) * ratio * 100) / 100;
      }
      next.receivedTotal = (next.receivedRent || 0) + (next.receivedDeposit || 0) + (next.receivedService || 0);
      return next;
    });
  } else {
    vehicles = vehicles.map(function (v) {
      var next = Object.assign({}, v);
      next.receivedRent = next.receivedRent != null ? next.receivedRent : 0;
      next.receivedDeposit = next.receivedDeposit != null ? next.receivedDeposit : 0;
      next.receivedService = next.receivedService != null ? next.receivedService : 0;
      next.receivedTotal = next.receivedTotal != null
        ? next.receivedTotal
        : next.receivedRent + next.receivedDeposit + next.receivedService;
      return next;
    });
  }

  child.deliveryVehicles = vehicles;
  return child;
}

export function enrichPickupRecord(record) {
  var next = Object.assign({}, record);
  var months = next.paymentCycleMonths || 1;
  if (!next.leaseOrderVehicles || !next.leaseOrderVehicles.length) {
    next.leaseOrderVehicles = vehiclesFromLeaseListRecord(next, months);
  }
  next.children = (next.children || []).map(function (child) {
    return enrichChildDeliveryVehicles(Object.assign({}, child), next);
  });
  next.contractVehicleCount = next.contractVehicleCount != null
    ? next.contractVehicleCount
    : next.leaseOrderVehicles.length;
  next.pickedUpVehicleCount = countPickedUpVehicles(next);
  var contractPickupDate = next.lastPickupDate || next.pickupDate;
  var receivableBreakdown = calcContractReceivableBreakdown(
    next.leaseOrderVehicles,
    months,
    contractPickupDate,
  );
  next.totalReceivableRent = receivableBreakdown.rent;
  next.totalReceivableDeposit = receivableBreakdown.deposit;
  next.totalReceivableService = receivableBreakdown.service;
  next.totalReceivableAmount = calcContractReceivableTotal(
    next.leaseOrderVehicles,
    months,
    contractPickupDate,
  );
  var receivedBreakdown = calcReceivedBreakdown(next.children);
  next.totalReceivedRent = receivedBreakdown.rent;
  next.totalReceivedDeposit = receivedBreakdown.deposit;
  next.totalReceivedService = receivedBreakdown.service;
  next.totalReceivedAmount = calcReceivedTotal(next.children);
  next.allVehiclesReceivableCompleted = next.pickedUpVehicleCount >= next.contractVehicleCount
    && next.contractVehicleCount > 0;
  return next;
}

function readPickupListFromStorageKey(key) {
  if (typeof window === 'undefined' || !window.localStorage) return null;
  try {
    var raw = window.localStorage.getItem(key);
    if (!raw) return null;
    var parsed = JSON.parse(raw);
    if (!Array.isArray(parsed)) return null;
    return parsed
      .filter(isValidPickupMainRecord)
      .map(enrichPickupRecord);
  } catch (e) {
    return null;
  }
}

export function loadStoredPickupList() {
  var current = readPickupListFromStorageKey(PICKUP_RECEIVABLE_STORAGE_KEY);
  if (current && current.length) return current;
  for (var i = 0; i < LEGACY_PICKUP_STORAGE_KEYS.length; i += 1) {
    var legacy = readPickupListFromStorageKey(LEGACY_PICKUP_STORAGE_KEYS[i]);
    if (legacy && legacy.length) return legacy;
  }
  return null;
}

export function saveStoredPickupList(list) {
  if (typeof window === 'undefined' || !window.localStorage) return;
  try {
    window.localStorage.setItem(
      PICKUP_RECEIVABLE_STORAGE_KEY,
      JSON.stringify((list || []).map(enrichPickupRecord)),
    );
  } catch (e) {
    /* ignore quota */
  }
}

export function upsertPickupRecord(list, record) {
  if (!isValidPickupMainRecord(record)) return (list || []).filter(isValidPickupMainRecord).map(enrichPickupRecord);
  var enriched = enrichPickupRecord(record);
  var idx = (list || []).findIndex(function (r) {
    return r.contractCode === enriched.contractCode;
  });
  var next = (list || []).slice();
  if (idx >= 0) {
    var existing = next[idx];
    next[idx] = Object.assign({}, existing, enriched, {
      children: enriched.children != null ? enriched.children : existing.children,
    });
  } else {
    next.unshift(enriched);
  }
  return next.map(enrichPickupRecord);
}

/** 租赁合同列表修改交车安排后，同步至提车应收款主记录 */
export function syncPickupReceivableDeliveryPlan(contractCode, patch) {
  var stored = loadStoredPickupList();
  if (!stored) return false;
  var found = false;
  var next = stored.map(function (row) {
    if (row.contractCode !== contractCode) return row;
    found = true;
    return enrichPickupRecord(Object.assign({}, row, patch || {}));
  });
  if (found) saveStoredPickupList(next);
  return found;
}

/** 租赁合同提交审核时同步创建提车应收款主记录 */
export function createPickupReceivableFromLeaseSubmit(payload) {
  var months = parsePaymentCycleMonths(payload.feeInfo || payload.paymentPeriod);
  var leaseOrderVehicles = payload.leaseOrder
    ? expandLeaseOrderToVehicles(payload.leaseOrder, months)
    : vehiclesFromLeaseListRecord(payload, months);

  var record = enrichPickupRecord({
    contractCode: payload.contractCode,
    contractType: payload.contractType || '正式合同',
    projectName: payload.projectName || '',
    customerName: payload.customerName || '',
    businessDept: payload.businessDept || '',
    businessPerson: payload.businessPerson || '',
    contractEffectiveDate: payload.contractEffectiveDate || payload.contractStart || '',
    contractApprovalStatus: '待审批',
    contractStatus: payload.contractStatus || '已提交审批',
    paymentCycleMonths: months,
    paymentMethod: (payload.feeInfo && payload.feeInfo.paymentMethod) || payload.paymentMethod || '预付',
    leaseOrderVehicles: leaseOrderVehicles,
    contractVehicleCount: leaseOrderVehicles.length,
    children: [],
    createdFromLeaseSubmit: true,
    createdAt: new Date().toISOString(),
  });

  var stored = loadStoredPickupList() || [];
  var next = upsertPickupRecord(stored, record);
  saveStoredPickupList(next);
  return record;
}

/** 租赁合同审批终止/驳回时标记可退款 */
export function syncPickupReceivableContractStatus(contractCode, patch) {
  var stored = loadStoredPickupList();
  if (!stored) return null;
  var found = false;
  var next = stored.map(function (row) {
    if (row.contractCode !== contractCode) return row;
    found = true;
    return enrichPickupRecord(Object.assign({}, row, patch));
  });
  if (found) saveStoredPickupList(next);
  return found ? next : null;
}

export function buildPickupSubmitCcMessage() {
  return '已快速生成提车应收款单据，审批中心已抄送「财务」';
}

/** 办理提交后追加子单（提车应收款单据） */
export function appendPickupCollectChild(contractCode, payload) {
  var stored = loadStoredPickupList();
  if (!stored) return null;
  var parent = stored.find(function (r) {
    return r.contractCode === contractCode;
  });
  if (!parent) return null;
  var children = (parent.children || []).slice();
  var seq = children.length + 1;
  var deliveryVehicles = (payload && payload.deliveryVehicles) || [];
  var schedule = (payload && payload.receivableSchedule) || null;
  var scheduleBreakdown = breakdownFromBatchSummary(schedule);
  var child = {
    seq: seq,
    documentType: '提车应收款',
    auditStatus: '已生成',
    creator: (payload && payload.creator) || '当前用户',
    chargeTime:
      (payload && payload.chargeTime)
      || new Date().toISOString().slice(0, 16).replace('T', ' '),
    pickupDate: (payload && payload.pickupDate) || '',
    deliveryLocation: (payload && payload.deliveryLocation) || formatDeliveryLocation(parent),
    receivableSchedule: schedule,
    receivableRent: parseFloat(payload && payload.receivableRent) || scheduleBreakdown.rent,
    receivableDeposit: parseFloat(payload && payload.receivableDeposit) || scheduleBreakdown.deposit,
    receivableService: parseFloat(payload && payload.receivableService) || scheduleBreakdown.service,
    receivedRent: parseFloat(payload && payload.receivedRent) || 0,
    receivedDeposit: parseFloat(payload && payload.receivedDeposit) || 0,
    receivedService: parseFloat(payload && payload.receivedService) || 0,
    deliveryCount: deliveryVehicles.length,
    deliveryVehicles: deliveryVehicles,
    receivableTotal: parseFloat(payload && payload.receivableTotal) || 0,
    actualTotal: parseFloat(payload && payload.actualTotal) || 0,
    discountTotal: parseFloat(payload && payload.discountTotal) || 0,
    arrivalAmount: 0,
    financeReceived: 0,
    isInvoiced: '未开票',
    invoicedAmount: 0,
    ccFinance: true,
    paymentImportNote: '实收金额由财务在「收款记录」导入到账后反写',
  };
  children.push(child);
  var next = upsertPickupRecord(stored, Object.assign({}, parent, {
    children: children,
    lastPickupDate: (payload && payload.pickupDate) || parent.lastPickupDate,
  }));
  saveStoredPickupList(next);
  return child;
}

export function formatLeaseContractCode(code) {
  var s = String(code || '').trim();
  if (!s) return '';
  return s.indexOf('HT-ZL-') === 0 ? s : 'HT-ZL-' + s;
}

export function toCollectPageVehicles(record, pickupDate) {
  var months = record.paymentCycleMonths || 1;
  var pickedKeys = collectPickedVehicleKeys(record.children);
  var dateStr = pickupDate || record.pickupDate || '';

  return (record.leaseOrderVehicles || []).map(function (v, index) {
    var key = vehicleMatchKey(v);
    var completed = pickedKeys.has(key);
    var schedule = dateStr
      ? buildVehiclePickupSchedule({
        monthRent: v.monthRent,
        monthServiceFee: v.serviceFeeTotal,
        deposit: v.deposit,
        pickupDate: dateStr,
        paymentCycleMonths: months,
      })
      : null;
    var pre = schedule && schedule.items[0];
    var preRent = pre ? pre.rent : 0;
    var preService = pre ? pre.service : 0;
    var preDeposit = pre ? pre.deposit : v.deposit || 0;
    var serviceItems = [
      {
        name: '月服务费（按提车日折算）',
        receivable: preService,
        actual: String((preService || 0).toFixed(2)),
        discount: '0.00',
        remark: schedule
          ? '当月实际租赁 ' + schedule.actualDays + ' 天，公式（月租金+月服务费）/30×天数'
          : '',
      },
    ];
    return {
      key: v.key || 'v' + (index + 1),
      index: v.seq || index + 1,
      brand: v.brand,
      model: v.model,
      plateNo: v.plateNo || '',
      monthRent: v.monthRent,
      serviceFeeTotal: v.serviceFeeTotal,
      deposit: v.deposit,
      receivableSchedule: schedule,
      receivableRent: preRent,
      actualRent: String((preRent || 0).toFixed(2)),
      rentRemark: '',
      receivableDeposit: preDeposit,
      serviceItems: serviceItems,
      receivableService: preService,
      actualService: String((preService || 0).toFixed(2)),
      discountAmount: '0.00',
      discountRemark: '',
      discountProof: [],
      selected: !completed,
      receivableCompleted: completed,
      receivableTotalAll: schedule ? schedule.totalReceivable : 0,
      receivableMonth25: schedule ? schedule.month25Amount : 0,
    };
  });
}

export function applyPickupDateToVehicles(vehicles, pickupDate, paymentCycleMonths) {
  return (vehicles || []).map(function (row) {
    if (row.receivableCompleted) return row;
    var schedule = buildVehiclePickupSchedule({
      monthRent: row.monthRent,
      monthServiceFee: row.serviceFeeTotal != null ? row.serviceFeeTotal : row.receivableService,
      deposit: row.receivableDeposit != null ? row.receivableDeposit : row.deposit,
      pickupDate: pickupDate,
      paymentCycleMonths: paymentCycleMonths,
    });
    if (!schedule) return row;
    var pre = schedule.items[0];
    var serviceFee = pre ? pre.service : 0;
    return Object.assign({}, row, {
      receivableSchedule: schedule,
      receivableRent: pre ? pre.rent : 0,
      actualRent: String(((pre && pre.rent) || 0).toFixed(2)),
      receivableDeposit: pre ? pre.deposit : row.receivableDeposit,
      receivableService: serviceFee,
      actualService: String(serviceFee.toFixed(2)),
      receivableTotalAll: schedule.totalReceivable,
      receivableMonth25: schedule.month25Amount,
      serviceItems: [
        {
          name: '月服务费（按提车日折算）',
          receivable: serviceFee,
          actual: String(serviceFee.toFixed(2)),
          discount: '0.00',
          remark: '当月实际租赁 ' + schedule.actualDays + ' 天',
        },
      ],
    });
  });
}
