// 【重要】必须使用 const Component 作为组件变量名
// ONE-OS 小程序 - 提车应收款审批办理（参照 web 端提车应收款-查看，适配移动端）

const { useState, useMemo, useCallback, useRef, useEffect } = React;
const moment = window.moment || window.dayjs;

const COLOR_PRIMARY = '#16D1A1';
const COLOR_PRIMARY_DEEP = '#00BFA5';
const COLOR_PRIMARY_SOFT = 'rgba(22, 209, 161, 0.12)';
const COLOR_ACCENT = '#F97316';
const COLOR_ACCENT_DEEP = '#EA580C';
const COLOR_ACCENT_SOFT = 'rgba(249, 115, 22, 0.12)';
const COLOR_TEXT = '#1D2129';
const COLOR_TEXT_SEC = '#4E5969';
const COLOR_MUTED = '#86909C';
const COLOR_LINE = '#E5E6EB';
const COLOR_BG = '#FFFFFF';
const COLOR_PAGE = '#F2F3F5';
const COLOR_SUCCESS = '#00B42A';
const COLOR_DANGER = '#F53F3F';
const COLOR_WARN = '#FF7D00';
const FONT_FAMILY =
  '-apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", STHeiti, sans-serif';

const resolveAntdBundle = () => {
  const raw = window.antd;
  if (!raw) return {};
  if (raw.default && typeof raw.default === 'object') return { ...raw, ...raw.default };
  return raw;
};

const antd = resolveAntdBundle();
const message = antd.message || { info: () => {}, success: () => {}, warning: () => {} };
const Drawer = antd.Drawer;
const Modal = antd.Modal;

const formatMoney = (val, withSymbol = true) => {
  const n = parseFloat(val);
  if (Number.isNaN(n)) return val || '—';
  const s = n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  return withSymbol ? `¥${s}` : s;
};

const formatYuan = (val) => {
  const n = parseFloat(val);
  if (Number.isNaN(n)) return '—';
  return `${n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} 元`;
};

/** 根据审批任务构建详情 mock（与 web 端字段对齐） */
const buildPickupDetail = (task) => {
  const isShanghai = task?.bizNo === 'TC-2026-0312';
  const projectInfo = isShanghai
    ? {
        collectCode: 'HT-ZL-2025-088TC0001',
        contractCode: 'HT-ZL-2025-088',
        contractType: '正式合同',
        projectName: '上海氢能城际物流项目',
        customerName: '上海迅杰物流有限公司',
        paymentMethod: '预付',
        paymentCycle: '6个月',
        contractStart: '2025-03-01',
        contractEnd: '2026-02-28',
        businessDept: '业务2部',
        businessPerson: '李晓彤',
      }
    : {
        collectCode: 'HT-ZL-2025-001TC0001',
        contractCode: 'HT-ZL-2025-001',
        contractType: '正式合同',
        projectName: '嘉兴氢能示范项目',
        customerName: '嘉兴某某物流有限公司',
        paymentMethod: '预付',
        paymentCycle: '6个月',
        contractStart: '2025-01-15',
        contractEnd: '2026-01-14',
        businessDept: '业务1部',
        businessPerson: '张经理',
      };

  const vehicles = isShanghai
    ? [
        {
          key: 'v1', index: 1, brand: '东风', model: 'DFH1180', plateNo: '沪A88123',
          receivableRent: 62000, actualRent: '61200.00', rentRemark: '首期六期一次性付清',
          receivableDeposit: 12000, receivableService: 880, actualService: '860.00',
          discountAmount: '200.00', discountRemark: '首月优惠',
          serviceItems: [
            { name: '代处理费用', receivable: 280, actual: '280.00', discount: '0.00', remark: '' },
            { name: '保险上浮', receivable: 600, actual: '580.00', discount: '20.00', remark: '客户协商' },
          ],
        },
        {
          key: 'v2', index: 2, brand: '福田', model: 'BJ1180', plateNo: '沪A88234',
          receivableRent: 58000, actualRent: '58000.00', rentRemark: '',
          receivableDeposit: 10000, receivableService: 500, actualService: '500.00',
          discountAmount: '0.00', discountRemark: '',
          serviceItems: [{ name: '保养费用', receivable: 500, actual: '500.00', discount: '0.00', remark: '含首保' }],
        },
        {
          key: 'v3', index: 3, brand: '重汽', model: 'ZZ1187', plateNo: '沪A88345',
          receivableRent: 64000, actualRent: '63600.00', rentRemark: '按合同约定',
          receivableDeposit: 12000, receivableService: 720, actualService: '700.00',
          discountAmount: '150.00', discountRemark: '批量提车减免',
          serviceItems: [
            { name: '代处理费用', receivable: 220, actual: '220.00', discount: '0.00', remark: '' },
            { name: '上牌服务', receivable: 500, actual: '480.00', discount: '20.00', remark: '已含上牌' },
          ],
        },
      ]
    : [
        {
          key: 'v1', index: 1, brand: '东风', model: 'DFH1180', plateNo: '浙A12345',
          receivableRent: 30000, actualRent: '29800.00', rentRemark: '首期六期一次性付清',
          receivableDeposit: 10000, receivableService: 700, actualService: '680.00',
          discountAmount: '200.00', discountRemark: '首月优惠',
          serviceItems: [
            { name: '代处理费用', receivable: 200, actual: '200.00', discount: '0.00', remark: '' },
            { name: '保险上浮', receivable: 500, actual: '480.00', discount: '20.00', remark: '客户协商' },
          ],
        },
        {
          key: 'v2', index: 2, brand: '福田', model: 'BJ1180', plateNo: '浙A23456',
          receivableRent: 27000, actualRent: '27000.00', rentRemark: '',
          receivableDeposit: 8000, receivableService: 300, actualService: '300.00',
          discountAmount: '0.00', discountRemark: '',
          serviceItems: [{ name: '保养费用', receivable: 300, actual: '300.00', discount: '0.00', remark: '含首保' }],
        },
      ];

  const hasHydrogenPrepay = true;
  const hydrogen = isShanghai
    ? { receivable: '4200.00', actual: '4100.00', discount: '100.00', discountRemark: '预付款批量减免' }
    : { receivable: '3580.00', actual: '3500.00', discount: '80.00', discountRemark: '预付款批量减免' };

  const approvalSteps = isShanghai
    ? [
        { title: '业务部主管', department: '业务2部', status: '已通过', person: '李晓彤', approveTime: '2026-05-30 10:30' },
        { title: '财务部', department: '财务部', status: '待审批', person: '张明辉', approveTime: '—' },
      ]
    : [
        { title: '业务部主管', department: '业务1部', status: '已通过', person: '张经理', approveTime: '2026-02-28 09:30' },
        { title: '财务部', department: '财务部', status: '已通过', person: '李财务', approveTime: '2026-02-28 10:15' },
        { title: '事业部主管', department: '事业部', status: '已通过', person: '王总', approveTime: '2026-03-01 11:20' },
      ];

  return {
    projectInfo,
    vehicles,
    hasHydrogenPrepay,
    hydrogen,
    approvalSteps,
    invoiceMethod: '先开票后付款',
    invoiceRemark: isShanghai
      ? '增值税专用发票，税率13%，开票项目：*现代服务*车辆租赁费；备注：上海氢能城际物流项目-提车首付款'
      : '增值税专用发票，税率13%，开票项目：*现代服务*车辆租赁费；备注：嘉兴氢能示范项目-提车首付款',
    task: task || { bizNo: 'TC-2026-0312', status: '审批中' },
  };
};

const calcTotals = (vehicles, hasHydrogenPrepay, hydrogen) => {
  let receivableRent = 0;
  let actualRent = 0;
  let receivableDeposit = 0;
  let receivableService = 0;
  let actualService = 0;
  let discountTotal = 0;
  vehicles.forEach((v) => {
    receivableRent += Number(v.receivableRent) || 0;
    actualRent += parseFloat(v.actualRent) || 0;
    receivableDeposit += Number(v.receivableDeposit) || 0;
    receivableService += Number(v.receivableService) || 0;
    actualService += parseFloat(v.actualService) || 0;
    discountTotal += parseFloat(v.discountAmount) || 0;
  });
  const hydrogenReceivable = hasHydrogenPrepay ? (parseFloat(hydrogen.receivable) || 0) : 0;
  const hydrogenActual = hasHydrogenPrepay ? (parseFloat(hydrogen.actual) || 0) : 0;
  const receivableTotal = (
    receivableRent + receivableDeposit + receivableService + hydrogenReceivable
  ).toFixed(2);
  const actualTotal = (
    actualRent + receivableDeposit + actualService - discountTotal + hydrogenActual
  ).toFixed(2);
  return {
    receivableRent: receivableRent.toFixed(2),
    actualRent: actualRent.toFixed(2),
    receivableDeposit: receivableDeposit.toFixed(2),
    receivableService: receivableService.toFixed(2),
    actualService: actualService.toFixed(2),
    discountTotal: discountTotal.toFixed(2),
    receivableTotal,
    actualTotal,
  };
};

const PAGE_STYLE = `
.tc-mini-root {
  min-height: 100dvh;
  background: linear-gradient(165deg, #e8ebef 0%, ${COLOR_PAGE} 40%);
  display: flex;
  justify-content: center;
  padding: 16px 12px 32px;
  box-sizing: border-box;
  font-family: ${FONT_FAMILY};
  -webkit-font-smoothing: antialiased;
}
.tc-phone {
  width: 100%;
  max-width: 390px;
  min-height: 844px;
  background: ${COLOR_PAGE};
  border-radius: 28px;
  overflow: hidden;
  box-shadow: 0 24px 48px rgba(15, 23, 42, 0.14), 0 0 0 1px rgba(15, 23, 42, 0.05);
  display: flex;
  flex-direction: column;
  position: relative;
}
.tc-chrome { flex-shrink: 0; background: ${COLOR_BG}; }
.tc-status-bar {
  height: 44px;
  padding: 14px 24px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
}
.tc-status-time { font-size: 15px; font-weight: 600; color: ${COLOR_TEXT}; }
.tc-mp-navbar {
  height: 48px;
  display: flex;
  align-items: center;
  padding: 0 8px 0 4px;
  border-bottom: 1px solid rgba(0,0,0,.05);
  position: relative;
  background: ${COLOR_BG};
}
.tc-mp-back {
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  color: ${COLOR_TEXT};
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.tc-mp-back:active { background: rgba(0,0,0,.05); }
.tc-mp-navbar-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: 17px;
  font-weight: 700;
  color: ${COLOR_TEXT};
  max-width: 56%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tc-scroll {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding-bottom: 88px;
}
.tc-hero {
  margin: 12px 14px 0;
  padding: 18px 16px 16px;
  border-radius: 16px;
  background: linear-gradient(135deg, ${COLOR_ACCENT} 0%, ${COLOR_ACCENT_DEEP} 100%);
  color: #fff;
  box-shadow: 0 10px 28px rgba(249, 115, 22, 0.35);
}
.tc-hero-label { font-size: 13px; opacity: 0.92; margin-bottom: 6px; }
.tc-hero-amount {
  font-size: 36px;
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.tc-hero-sub {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255,255,255,.22);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.tc-hero-compare { font-size: 12px; opacity: 0.9; line-height: 1.45; }
.tc-hero-detail-btn {
  flex-shrink: 0;
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid rgba(255,255,255,.45);
  border-radius: 999px;
  background: rgba(255,255,255,.14);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.tc-hero-detail-btn:active { background: rgba(255,255,255,.24); }
.tc-hero-meta {
  display: flex;
  gap: 16px;
  margin-top: 10px;
  font-size: 12px;
  opacity: 0.88;
}
.tc-section {
  margin: 12px 14px 0;
  background: ${COLOR_BG};
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.04);
  border: 1px solid rgba(0,0,0,.04);
}
.tc-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid ${COLOR_LINE};
}
.tc-section-title { font-size: 15px; font-weight: 700; color: ${COLOR_TEXT}; }
.tc-section-badge {
  font-size: 11px;
  font-weight: 600;
  color: ${COLOR_ACCENT};
  background: ${COLOR_ACCENT_SOFT};
  padding: 2px 8px;
  border-radius: 999px;
}
.tc-kv-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 14px;
  padding: 12px 14px 14px;
}
.tc-kv-item { min-width: 0; }
.tc-kv-label { font-size: 11px; color: ${COLOR_MUTED}; margin-bottom: 3px; }
.tc-kv-value {
  font-size: 13px;
  color: ${COLOR_TEXT};
  font-weight: 500;
  line-height: 1.4;
  word-break: break-all;
}
.tc-kv-value--full { grid-column: 1 / -1; }
.tc-vehicle-card {
  margin: 0 14px 10px;
  padding: 12px 14px;
  background: ${COLOR_PAGE};
  border-radius: 12px;
  border: 1px solid ${COLOR_LINE};
}
.tc-vehicle-card:last-child { margin-bottom: 14px; }
.tc-vehicle-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.tc-vehicle-plate {
  font-size: 15px;
  font-weight: 700;
  color: ${COLOR_TEXT};
  font-variant-numeric: tabular-nums;
}
.tc-vehicle-model { font-size: 12px; color: ${COLOR_MUTED}; margin-top: 2px; }
.tc-vehicle-idx {
  font-size: 11px;
  font-weight: 700;
  color: ${COLOR_ACCENT};
  background: ${COLOR_ACCENT_SOFT};
  padding: 2px 8px;
  border-radius: 999px;
  flex-shrink: 0;
}
.tc-vehicle-amount-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  background: ${COLOR_BG};
  border-radius: 10px;
  margin-bottom: 8px;
}
.tc-vehicle-amount-label { font-size: 12px; color: ${COLOR_MUTED}; }
.tc-vehicle-amount-val {
  font-size: 18px;
  font-weight: 800;
  color: ${COLOR_ACCENT};
  font-variant-numeric: tabular-nums;
}
.tc-vehicle-kv {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 10px;
}
.tc-vehicle-kv-item { font-size: 12px; color: ${COLOR_TEXT_SEC}; }
.tc-vehicle-kv-item span { color: ${COLOR_MUTED}; }
.tc-service-toggle {
  width: 100%;
  margin-top: 8px;
  min-height: 32px;
  border: none;
  background: transparent;
  color: ${COLOR_PRIMARY_DEEP};
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
  padding: 0;
}
.tc-service-list {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed ${COLOR_LINE};
}
.tc-service-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 8px;
  font-size: 12px;
  padding: 6px 0;
  border-bottom: 1px solid rgba(0,0,0,.04);
}
.tc-service-row:last-child { border-bottom: none; }
.tc-service-name { color: ${COLOR_TEXT}; font-weight: 500; }
.tc-service-amt { color: ${COLOR_ACCENT}; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; }
.tc-service-sub { grid-column: 1 / -1; color: ${COLOR_MUTED}; font-size: 11px; }
.tc-timeline { padding: 4px 14px 14px; }
.tc-step {
  display: flex;
  gap: 12px;
  position: relative;
  padding-bottom: 16px;
}
.tc-step:last-child { padding-bottom: 0; }
.tc-step:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 9px;
  top: 22px;
  bottom: 0;
  width: 2px;
  background: ${COLOR_LINE};
}
.tc-step-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  margin-top: 1px;
}
.tc-step-dot.done { background: ${COLOR_SUCCESS}; color: #fff; }
.tc-step-dot.wait { background: ${COLOR_ACCENT_SOFT}; color: ${COLOR_ACCENT}; border: 2px solid ${COLOR_ACCENT}; box-sizing: border-box; }
.tc-step-body { flex: 1; min-width: 0; }
.tc-step-title { font-size: 14px; font-weight: 600; color: ${COLOR_TEXT}; }
.tc-step-meta { font-size: 12px; color: ${COLOR_MUTED}; margin-top: 4px; line-height: 1.5; }
.tc-action-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(255,255,255,.96);
  border-top: 1px solid ${COLOR_LINE};
  backdrop-filter: blur(8px);
}
.tc-action-bar--view { justify-content: flex-end; }
.tc-btn {
  flex: 1;
  min-height: 44px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  touch-action: manipulation;
  border: none;
}
.tc-btn-comment { flex: 0 0 auto; min-width: 64px; background: ${COLOR_BG}; color: ${COLOR_TEXT_SEC}; border: 1px solid ${COLOR_LINE}; }
.tc-btn-terminate { background: ${COLOR_PAGE}; color: ${COLOR_WARN}; border: 1px solid rgba(255, 125, 0, 0.3); }
.tc-btn-reject {
  background: ${COLOR_PAGE};
  color: ${COLOR_DANGER};
  border: 1px solid rgba(245, 63, 63, 0.25);
}
.tc-btn-approve {
  background: linear-gradient(135deg, ${COLOR_PRIMARY} 0%, ${COLOR_PRIMARY_DEEP} 100%);
  color: #fff;
  box-shadow: 0 4px 14px rgba(0, 191, 165, 0.3);
}
.tc-btn:active { opacity: 0.92; transform: scale(0.98); }
.tc-approval-form { display: flex; flex-direction: column; gap: 16px; padding: 4px 0 8px; }
.tc-form-field { display: flex; flex-direction: column; gap: 8px; }
.tc-form-label { font-size: 14px; color: ${COLOR_TEXT}; font-weight: 500; }
.tc-form-label-required::before { content: '*'; color: ${COLOR_DANGER}; margin-right: 4px; }
.tc-notify-group { display: flex; flex-wrap: wrap; gap: 16px; }
.tc-notify-item { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: ${COLOR_TEXT_SEC}; cursor: pointer; min-height: 32px; }
.tc-notify-item input { width: 16px; height: 16px; accent-color: ${COLOR_PRIMARY}; }
.tc-notify-item.disabled { opacity: 0.55; cursor: not-allowed; }
.tc-upload-btn {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 14px;
  border: 1px dashed ${COLOR_LINE}; border-radius: 8px; background: ${COLOR_PAGE};
  color: ${COLOR_TEXT_SEC}; font-size: 13px; cursor: pointer;
}
.tc-upload-hint { font-size: 12px; color: ${COLOR_MUTED}; line-height: 1.55; margin-top: 4px; }
.tc-file-list { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.tc-file-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px; background: ${COLOR_PAGE}; border-radius: 8px; font-size: 13px; color: ${COLOR_TEXT}; }
.tc-file-remove { border: none; background: transparent; color: ${COLOR_MUTED}; font-size: 12px; cursor: pointer; padding: 4px; }
.tc-select-person {
  min-height: 44px; padding: 0 14px; border: 1px solid ${COLOR_LINE}; border-radius: 10px;
  background: ${COLOR_BG}; color: ${COLOR_MUTED}; font-size: 14px; text-align: left; cursor: pointer; width: 100%;
}
.tc-select-person.has-value { color: ${COLOR_TEXT}; }
.tc-cc-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.tc-cc-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 999px;
  background: ${COLOR_PRIMARY_SOFT}; color: ${COLOR_PRIMARY_DEEP}; font-size: 12px; font-weight: 600;
}
.tc-cc-chip button { border: none; background: transparent; color: inherit; cursor: pointer; padding: 0 2px; font-size: 14px; line-height: 1; }
.tc-textarea {
  width: 100%; min-height: 96px; padding: 10px 12px; border: 1px solid ${COLOR_LINE}; border-radius: 10px;
  font-size: 14px; color: ${COLOR_TEXT}; resize: vertical; box-sizing: border-box; font-family: inherit; outline: none;
}
.tc-textarea:focus { border-color: rgba(22, 209, 161, 0.55); box-shadow: 0 0 0 3px rgba(22, 209, 161, 0.12); }
.tc-textarea-counter { text-align: right; font-size: 12px; color: ${COLOR_MUTED}; margin-top: 4px; }
.tc-drawer-foot { display: flex; gap: 10px; padding-top: 12px; margin-top: 4px; border-top: 1px solid ${COLOR_LINE}; }
.tc-drawer-foot-btn { flex: 1; min-height: 44px; border-radius: 10px; font-size: 15px; font-weight: 600; cursor: pointer; border: none; }
.tc-drawer-foot-cancel { background: ${COLOR_BG}; color: ${COLOR_TEXT_SEC}; border: 1px solid ${COLOR_LINE}; }
.tc-drawer-foot-confirm { background: #1677ff; color: #fff; }
.tc-person-list { display: flex; flex-direction: column; gap: 8px; }
.tc-person-item {
  min-height: 48px; padding: 0 14px; border: 1px solid ${COLOR_LINE}; border-radius: 10px;
  background: ${COLOR_BG}; font-size: 14px; color: ${COLOR_TEXT}; text-align: left; cursor: pointer;
}
.tc-person-item.selected { border-color: ${COLOR_PRIMARY}; background: ${COLOR_PRIMARY_SOFT}; color: ${COLOR_PRIMARY_DEEP}; font-weight: 600; }
.tc-drawer-rows { display: flex; flex-direction: column; gap: 0; }
.tc-drawer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid ${COLOR_LINE};
  font-size: 14px;
}
.tc-drawer-row:last-child { border-bottom: none; }
.tc-drawer-row-label { color: ${COLOR_TEXT_SEC}; }
.tc-drawer-row-val { font-weight: 700; color: ${COLOR_TEXT}; font-variant-numeric: tabular-nums; }
.tc-drawer-row-val.highlight { color: ${COLOR_ACCENT}; font-size: 16px; }
.tc-drawer-total {
  margin-top: 8px;
  padding-top: 12px;
  border-top: 2px solid ${COLOR_LINE};
  display: flex;
  justify-content: space-between;
  font-size: 15px;
  font-weight: 700;
}
.tc-drawer-total span:last-child { color: ${COLOR_ACCENT}; font-size: 18px; font-variant-numeric: tabular-nums; }
`;

const IconBack = () => (
  <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <polyline points="15 18 9 12 15 6" />
  </svg>
);

const InfoRow = ({ label, value, full }) => (
  <div className={`tc-kv-item${full ? ' tc-kv-value--full' : ''}`}>
    <div className="tc-kv-label">{label}</div>
    <div className="tc-kv-value">{value || '—'}</div>
  </div>
);

const VehicleCard = ({ vehicle }) => {
  const [serviceOpen, setServiceOpen] = useState(false);
  const vehicleActual = (
    parseFloat(vehicle.actualRent || 0)
    + parseFloat(vehicle.receivableDeposit || 0)
    + parseFloat(vehicle.actualService || 0)
    - parseFloat(vehicle.discountAmount || 0)
  ).toFixed(2);

  return (
    <div className="tc-vehicle-card">
      <div className="tc-vehicle-head">
        <div>
          <div className="tc-vehicle-plate">{vehicle.plateNo || '待上牌'}</div>
          <div className="tc-vehicle-model">{vehicle.brand} · {vehicle.model}</div>
        </div>
        <span className="tc-vehicle-idx">#{vehicle.index}</span>
      </div>
      <div className="tc-vehicle-amount-row">
        <span className="tc-vehicle-amount-label">本车实收合计</span>
        <span className="tc-vehicle-amount-val">{formatMoney(vehicleActual)}</span>
      </div>
      <div className="tc-vehicle-kv">
        <div className="tc-vehicle-kv-item"><span>实收月租金 </span>{formatYuan(vehicle.actualRent)}</div>
        <div className="tc-vehicle-kv-item"><span>应收保证金 </span>{formatYuan(vehicle.receivableDeposit)}</div>
        <div className="tc-vehicle-kv-item"><span>实收服务费 </span>{formatYuan(vehicle.actualService)}</div>
        <div className="tc-vehicle-kv-item"><span>减免金额 </span>{formatYuan(vehicle.discountAmount)}</div>
      </div>
      {vehicle.rentRemark ? (
        <div style={{ fontSize: 12, color: COLOR_MUTED, marginTop: 8 }}>租金备注：{vehicle.rentRemark}</div>
      ) : null}
      {(vehicle.serviceItems || []).length > 0 && (
        <>
          <button type="button" className="tc-service-toggle" onClick={() => setServiceOpen((o) => !o)}>
            {serviceOpen ? '收起' : '查看'}服务费明细（{(vehicle.serviceItems || []).length} 项）
          </button>
          {serviceOpen && (
            <div className="tc-service-list">
              {(vehicle.serviceItems || []).map((s, i) => (
                <div className="tc-service-row" key={i}>
                  <span className="tc-service-name">{s.name}</span>
                  <span className="tc-service-amt">{formatMoney(s.actual)}</span>
                  <span className="tc-service-sub">
                    应收 {formatYuan(s.receivable)} · 减免 {formatYuan(s.discount)}{s.remark ? ` · ${s.remark}` : ''}
                  </span>
                </div>
              ))}
            </div>
          )}
        </>
      )}
    </div>
  );
};

const AmountBreakdownDrawer = ({ open, onClose, title, rows, totalLabel, totalValue, highlightTotal }) => (
  Drawer ? (
    <Drawer title={title} placement="bottom" height="auto" open={open} onClose={onClose} styles={{ body: { padding: '8px 20px 24px' } }}>
      <div className="tc-drawer-rows">
        {rows.map((r) => (
          <div className="tc-drawer-row" key={r.label}>
            <span className="tc-drawer-row-label">{r.label}</span>
            <span className={`tc-drawer-row-val${r.highlight ? ' highlight' : ''}`}>{r.value}</span>
          </div>
        ))}
        <div className="tc-drawer-total">
          <span>{totalLabel}</span>
          <span>{totalValue}</span>
        </div>
      </div>
    </Drawer>
  ) : null
);

const APPROVAL_DECISION_META = {
  approve: { title: '审批通过', success: '审批已通过（原型）' },
  reject: { title: '审批驳回', success: '已驳回（原型）' },
  terminate: { title: '审批终止', success: '已终止（原型）' },
};

const MOCK_CC_CANDIDATES = ['李晓彤', '陈高伟', '王法务', '财务-赵敏'];
const UPLOAD_ACCEPT = '.png,.jpg,.jpeg,.doc,.docx,.xlsx,.xls,.ppt,.pdf';
const UPLOAD_HINT = '请上传不超过 20MB 的 png, jpg, jpeg, doc, docx, xlsx, xls, ppt, pdf 格式文件';

const emptyDecisionForm = () => ({
  notifyEmail: false,
  notifySms: false,
  ccUsers: [],
  opinion: '',
  attachments: [],
});

const ApprovalDecisionDrawer = ({ open, actionType, onClose, onConfirm }) => {
  const meta = APPROVAL_DECISION_META[actionType] || APPROVAL_DECISION_META.approve;
  const [form, setForm] = useState(emptyDecisionForm);
  const [ccPickerOpen, setCcPickerOpen] = useState(false);
  const fileInputRef = useRef(null);

  useEffect(() => {
    if (open) {
      setForm(emptyDecisionForm());
      setCcPickerOpen(false);
    }
  }, [open, actionType]);

  const handleDrawerClose = () => {
    if (ccPickerOpen) {
      setCcPickerOpen(false);
      return;
    }
    onClose();
  };

  const toggleCcUser = (name) => {
    setForm((p) => ({
      ...p,
      ccUsers: p.ccUsers.includes(name) ? p.ccUsers.filter((n) => n !== name) : [...p.ccUsers, name],
    }));
  };

  const handleUpload = (e) => {
    const files = Array.from(e.target.files || []);
    if (!files.length) return;
    setForm((p) => ({
      ...p,
      attachments: [
        ...p.attachments,
        ...files.map((f) => ({ id: `${f.name}-${Date.now()}`, name: f.name, size: f.size })),
      ],
    }));
    e.target.value = '';
  };

  const handleConfirm = () => {
    onConfirm?.({ actionType, ...form, notifyInternal: true });
    onClose();
  };

  if (!Drawer) return null;

  return (
    <Drawer
      title={ccPickerOpen ? '选择抄送人' : meta.title}
      placement="bottom"
      height={ccPickerOpen ? 360 : 'auto'}
      open={open}
      onClose={handleDrawerClose}
      destroyOnClose
      zIndex={1000}
      styles={{ body: { padding: '8px 16px 24px', maxHeight: ccPickerOpen ? undefined : '78vh', overflowY: 'auto' } }}
    >
      {ccPickerOpen ? (
        <>
          <div className="tc-person-list">
            {MOCK_CC_CANDIDATES.map((name) => (
              <button key={name} type="button" className={`tc-person-item${form.ccUsers.includes(name) ? ' selected' : ''}`} onClick={() => toggleCcUser(name)}>{name}</button>
            ))}
          </div>
          <div className="tc-drawer-foot">
            <button type="button" className="tc-drawer-foot-btn tc-drawer-foot-cancel" onClick={() => setCcPickerOpen(false)}>返回</button>
            <button type="button" className="tc-drawer-foot-btn tc-drawer-foot-confirm" onClick={() => setCcPickerOpen(false)}>确定</button>
          </div>
        </>
      ) : (
        <>
        <div className="tc-approval-form">
          <div className="tc-form-field">
            <div className="tc-form-label">通知方式</div>
            <div className="tc-notify-group">
              <label className="tc-notify-item disabled">
                <input type="checkbox" checked disabled readOnly />站内信
              </label>
              <label className="tc-notify-item">
                <input type="checkbox" checked={form.notifyEmail} onChange={(e) => setForm((p) => ({ ...p, notifyEmail: e.target.checked }))} />
                邮件
              </label>
              <label className="tc-notify-item">
                <input type="checkbox" checked={form.notifySms} onChange={(e) => setForm((p) => ({ ...p, notifySms: e.target.checked }))} />
                短信
              </label>
            </div>
          </div>
          <div className="tc-form-field">
            <div className="tc-form-label">附件上传</div>
            <button type="button" className="tc-upload-btn" onClick={() => fileInputRef.current?.click()}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><polyline points="17 8 12 3 7 8" /><line x1="12" y1="3" x2="12" y2="15" /></svg>
              上传
            </button>
            <input ref={fileInputRef} type="file" accept={UPLOAD_ACCEPT} multiple style={{ display: 'none' }} onChange={handleUpload} />
            <div className="tc-upload-hint">{UPLOAD_HINT}</div>
            {form.attachments.length > 0 && (
              <div className="tc-file-list">
                {form.attachments.map((f) => (
                  <div className="tc-file-item" key={f.id}>
                    <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.name}</span>
                    <button type="button" className="tc-file-remove" onClick={() => setForm((p) => ({ ...p, attachments: p.attachments.filter((a) => a.id !== f.id) }))}>删除</button>
                  </div>
                ))}
              </div>
            )}
          </div>
          <div className="tc-form-field">
            <div className="tc-form-label">抄送人</div>
            <button type="button" className={`tc-select-person${form.ccUsers.length ? ' has-value' : ''}`} onClick={() => setCcPickerOpen(true)}>
              {form.ccUsers.length ? `已选 ${form.ccUsers.length} 人` : '选择人员'}
            </button>
            {form.ccUsers.length > 0 && (
              <div className="tc-cc-chips">
                {form.ccUsers.map((name) => (
                  <span className="tc-cc-chip" key={name}>{name}<button type="button" onClick={() => toggleCcUser(name)}>×</button></span>
                ))}
              </div>
            )}
          </div>
          <div className="tc-form-field">
            <div className="tc-form-label">审批意见</div>
            <textarea className="tc-textarea" placeholder="请输入" value={form.opinion} onChange={(e) => setForm((p) => ({ ...p, opinion: e.target.value }))} maxLength={500} />
          </div>
        </div>
        <div className="tc-drawer-foot">
          <button type="button" className="tc-drawer-foot-btn tc-drawer-foot-cancel" onClick={onClose}>取消</button>
          <button type="button" className="tc-drawer-foot-btn tc-drawer-foot-confirm" onClick={handleConfirm}>确认</button>
        </div>
        </>
      )}
    </Drawer>
  );
};

const ApprovalCommentDrawer = ({ open, onClose, onConfirm }) => {
  const [content, setContent] = useState('');
  useEffect(() => { if (open) setContent(''); }, [open]);
  const handleConfirm = () => {
    if (!content.trim()) { message.warning('请输入评论内容'); return; }
    onConfirm?.({ content: content.trim() });
    onClose();
  };
  if (!Drawer) return null;
  return (
    <Drawer title="添加评论" placement="bottom" height="auto" open={open} onClose={onClose} destroyOnClose zIndex={1000} styles={{ body: { padding: '8px 16px 24px' } }}>
      <div className="tc-form-field">
        <div className="tc-form-label tc-form-label-required">评论内容</div>
        <textarea className="tc-textarea" placeholder="请输入评论内容" value={content} onChange={(e) => setContent(e.target.value.slice(0, 500))} maxLength={500} />
        <div className="tc-textarea-counter">{content.length} / 500</div>
      </div>
      <div className="tc-drawer-foot">
        <button type="button" className="tc-drawer-foot-btn tc-drawer-foot-cancel" onClick={onClose}>取消</button>
        <button type="button" className="tc-drawer-foot-btn tc-drawer-foot-confirm" onClick={handleConfirm}>确认</button>
      </div>
    </Drawer>
  );
};

const ApprovalActionBar = ({ mode, onComment, onTerminate, onReject, onApprove }) => {
  if (mode === 'approve') {
    return (
      <div className="tc-action-bar">
        <button type="button" className="tc-btn tc-btn-comment" onClick={onComment}>评论</button>
        <button type="button" className="tc-btn tc-btn-terminate" onClick={onTerminate}>终止</button>
        <button type="button" className="tc-btn tc-btn-reject" onClick={onReject}>驳回</button>
        <button type="button" className="tc-btn tc-btn-approve" onClick={onApprove}>通过</button>
      </div>
    );
  }
  return (
    <div className="tc-action-bar tc-action-bar--view">
      <button type="button" className="tc-btn tc-btn-comment" style={{ flex: '0 0 88px' }} onClick={onComment}>评论</button>
    </div>
  );
};

/** 可被审批中心内嵌调用的详情视图 */
const PickupReceivableApproveView = ({ task, mode = 'approve', onBack }) => {
  const detail = useMemo(() => buildPickupDetail(task), [task]);
  const { projectInfo, vehicles, hasHydrogenPrepay, hydrogen, approvalSteps, invoiceMethod, invoiceRemark } = detail;
  const totals = useMemo(
    () => calcTotals(vehicles, hasHydrogenPrepay, hydrogen),
    [vehicles, hasHydrogenPrepay, hydrogen]
  );
  const [actualDrawerOpen, setActualDrawerOpen] = useState(false);
  const [receivableDrawerOpen, setReceivableDrawerOpen] = useState(false);
  const [decisionOpen, setDecisionOpen] = useState(false);
  const [decisionType, setDecisionType] = useState('approve');
  const [commentOpen, setCommentOpen] = useState(false);
  const showActions = mode === 'approve' || mode === 'view';
  const displayActualTotal = task?.actualAmount || totals.actualTotal;

  const actualBreakdownRows = useMemo(() => {
    const rows = [
      { label: '总计实收车辆月租金', value: formatYuan(totals.actualRent) },
      { label: '总计应收车辆保证金', value: formatYuan(totals.receivableDeposit) },
      { label: '总计实收服务费', value: formatYuan(totals.actualService) },
      { label: '总计减免金额', value: `- ${formatYuan(totals.discountTotal)}` },
    ];
    if (hasHydrogenPrepay) {
      rows.push({ label: '氢费预充值实收金额', value: formatYuan(hydrogen.actual), highlight: true });
    }
    return rows;
  }, [totals, hasHydrogenPrepay, hydrogen.actual]);

  const receivableBreakdownRows = useMemo(() => {
    const rows = [
      { label: '总计应收车辆月租金', value: formatYuan(totals.receivableRent) },
      { label: '总计应收车辆保证金', value: formatYuan(totals.receivableDeposit) },
      { label: '总计应收服务费', value: formatYuan(totals.receivableService) },
    ];
    if (hasHydrogenPrepay) {
      rows.push({ label: '氢费预充值应收金额', value: formatYuan(hydrogen.receivable) });
    }
    return rows;
  }, [totals, hasHydrogenPrepay, hydrogen.receivable]);

  const openDecision = (type) => {
    setDecisionType(type);
    setDecisionOpen(true);
  };

  const handleDecisionConfirm = (payload) => {
    const meta = APPROVAL_DECISION_META[payload.actionType];
    if (payload.actionType === 'reject' || payload.actionType === 'terminate') {
      message.warning(meta?.success || '操作成功（原型）');
    } else {
      message.success(meta?.success || '操作成功（原型）');
    }
    if (mode === 'approve') onBack?.();
  };

  const handleCommentConfirm = () => {
    message.success('评论已添加（原型）');
  };

  const diff = (parseFloat(totals.receivableTotal) - parseFloat(displayActualTotal)).toFixed(2);

  return (
    <>
      <div className="tc-scroll">
        <div className="tc-hero">
          <div className="tc-hero-label">实收款总额</div>
          <div className="tc-hero-amount">{formatMoney(displayActualTotal)}</div>
          <div className="tc-hero-meta">
            <span>{projectInfo.customerName}</span>
            <span>{vehicles.length} 台车</span>
          </div>
          <div className="tc-hero-sub">
            <div className="tc-hero-compare">
              应收款总额 {formatMoney(totals.receivableTotal)}
              <br />
              较应收减免 {formatMoney(diff)}
            </div>
            <button type="button" className="tc-hero-detail-btn" onClick={() => setActualDrawerOpen(true)}>
              实收明细
            </button>
          </div>
        </div>

        <div className="tc-section">
          <div className="tc-section-head">
            <span className="tc-section-title">项目信息</span>
          </div>
          <div className="tc-kv-grid">
            <InfoRow label="提车收款单编码" value={projectInfo.collectCode} full />
            <InfoRow label="合同编码" value={projectInfo.contractCode} />
            <InfoRow label="合同类型" value={projectInfo.contractType} />
            <InfoRow label="项目名称" value={projectInfo.projectName} full />
            <InfoRow label="客户企业名称" value={projectInfo.customerName} full />
            <InfoRow label="付款方式" value={projectInfo.paymentMethod} />
            <InfoRow label="付款周期" value={projectInfo.paymentCycle} />
            <InfoRow label="合同生效" value={projectInfo.contractStart} />
            <InfoRow label="合同结束" value={projectInfo.contractEnd} />
            <InfoRow label="业务部门" value={projectInfo.businessDept} />
            <InfoRow label="业务负责人" value={projectInfo.businessPerson} />
          </div>
        </div>

        <div className="tc-section">
          <div className="tc-section-head">
            <span className="tc-section-title">提车应收款 · 车辆明细</span>
            <span className="tc-section-badge">{vehicles.length} 台</span>
          </div>
          {vehicles.map((v) => (
            <VehicleCard key={v.key} vehicle={v} />
          ))}
        </div>

        {hasHydrogenPrepay && (
          <div className="tc-section">
            <div className="tc-section-head">
              <span className="tc-section-title">氢费预付款</span>
            </div>
            <div className="tc-kv-grid">
              <InfoRow label="应收金额" value={formatYuan(hydrogen.receivable)} />
              <InfoRow label="实收金额" value={formatYuan(hydrogen.actual)} />
              <InfoRow label="减免金额" value={formatYuan(hydrogen.discount)} />
              <InfoRow label="减免备注" value={hydrogen.discountRemark} full />
            </div>
          </div>
        )}

        <div className="tc-section">
          <div className="tc-section-head">
            <span className="tc-section-title">开票信息</span>
          </div>
          <div className="tc-kv-grid">
            <InfoRow label="开票方式" value={invoiceMethod} />
            <InfoRow label="开票备注" value={invoiceRemark} full />
          </div>
        </div>

        <div className="tc-section">
          <div className="tc-section-head">
            <span className="tc-section-title">审批情况</span>
          </div>
          <div className="tc-timeline">
            {approvalSteps.map((step, idx) => (
              <div className="tc-step" key={idx}>
                <div className={`tc-step-dot ${step.status === '已通过' ? 'done' : 'wait'}`}>
                  {step.status === '已通过' ? '✓' : ''}
                </div>
                <div className="tc-step-body">
                  <div className="tc-step-title">{step.department || step.title}</div>
                  <div className="tc-step-meta">
                    状态：{step.status}<br />
                    审批人：{step.person}<br />
                    时间：{step.approveTime}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>

        <div style={{ height: showActions ? 16 : 24 }} />
      </div>

      {showActions && !decisionOpen && !commentOpen && (
        <ApprovalActionBar
          mode={mode}
          onComment={() => setCommentOpen(true)}
          onTerminate={() => openDecision('terminate')}
          onReject={() => openDecision('reject')}
          onApprove={() => openDecision('approve')}
        />
      )}
      <ApprovalDecisionDrawer
        open={decisionOpen}
        actionType={decisionType}
        onClose={() => setDecisionOpen(false)}
        onConfirm={handleDecisionConfirm}
      />
      <ApprovalCommentDrawer
        open={commentOpen}
        onClose={() => setCommentOpen(false)}
        onConfirm={handleCommentConfirm}
      />

      <AmountBreakdownDrawer
        open={actualDrawerOpen}
        onClose={() => setActualDrawerOpen(false)}
        title="实收款明细"
        rows={actualBreakdownRows}
        totalLabel="实收款总额"
        totalValue={formatMoney(displayActualTotal)}
        highlightTotal
      />
      <AmountBreakdownDrawer
        open={receivableDrawerOpen}
        onClose={() => setReceivableDrawerOpen(false)}
        title="应收款明细"
        rows={receivableBreakdownRows}
        totalLabel="应收款总额"
        totalValue={formatMoney(totals.receivableTotal)}
      />
    </>
  );
};

const MiniProgramChrome = ({ title, showBack, onBack }) => {
  const time = moment ? moment().format('HH:mm') : '9:41';
  return (
    <div className="tc-chrome">
      <div className="tc-status-bar">
        <span className="tc-status-time">{time}</span>
      </div>
      <div className="tc-mp-navbar">
        {showBack ? (
          <button type="button" className="tc-mp-back" onClick={onBack} aria-label="返回">
            <IconBack />
          </button>
        ) : (
          <span style={{ width: 40, flexShrink: 0 }} />
        )}
        <span className="tc-mp-navbar-title">{title}</span>
      </div>
    </div>
  );
};

const DEFAULT_TASK = {
  id: 'ap-2',
  flowType: '提车应收款',
  bizNo: 'TC-2026-0312',
  customerName: '上海迅杰物流有限公司',
  projectName: '上海氢能城际物流项目',
  vehicleCount: 3,
  actualAmount: '186800.00',
  status: '审批中',
};

const Component = function PickupReceivableApprovePage() {
  const task = window.__pickupApproveTask || DEFAULT_TASK;
  const mode = window.__pickupApproveMode || 'approve';

  const handleBack = () => {
    if (window.__pickupApproveBack) window.__pickupApproveBack();
    else message.info('返回审批中心（原型）');
  };

  return (
    <div className="tc-mini-root">
      <style>{PAGE_STYLE}</style>
      <div className="tc-phone">
        <MiniProgramChrome title="提车应收款审批" showBack onBack={handleBack} />
        <PickupReceivableApproveView task={task} mode={mode} onBack={handleBack} />
      </div>
    </div>
  );
};

if (typeof window !== 'undefined') {
  window.Component = Component;
  window.PickupReceivableApproveView = PickupReceivableApproveView;
  window.buildPickupDetail = buildPickupDetail;
  window.__tcPickupStyles = PAGE_STYLE;
}

export default Component;
