/* ===== pages-devices.jsx — devices ===== */
(function () {
  const { Icon, Button, IconBtn, Card, Badge, AlarmChip, EmptyState, Input, Field, Textarea,
    DateField, SearchableSelect, Table, Tabs, Modal,
    useStore, navigate, cls, fmtDate, fmtRel, fmtCurrency,
    ListShell, FormShell, KV, Stat, SupplierNew, CustomerNew } = window;

  /* ---------- Device Products ---------- */
  function DeviceProducts({ mobile }) {
    const store = useStore();
    const { device_products, device_units, suppliers } = store;
    const sup = (id) => suppliers.find((s) => s.id === id);
    const cnt = (pid) => device_units.filter((u) => u.product_id === pid).length;
    const cntFault = (pid) => device_units.filter((u) => u.product_id === pid && u.status === 'FAULT').length;

    const columns = [
      { header: '型号', cell: (p) => (
        <div className="flex items-center gap-3">
          <span className="h-10 w-10 rounded-md stripe-bg ring-1 ring-ink-200 flex items-center justify-center">
            <Icon.cpu size={16} className="text-ink-400" />
          </span>
          <div>
            <div className="text-sm font-medium">{p.name}</div>
            <div className="text-xs text-ink-500 font-mono">{p.brand} · {p.model}</div>
          </div>
        </div>
      )},
      { header: '类别', cell: (p) => <Badge tone="sky">{p.category}</Badge> },
      { header: '厂家', cell: (p) => <span className="text-sm">{sup(p.supplier_id)?.short}</span> },
      { header: '在管', align: 'right', cell: (p) => <span className="font-mono text-sm">{cnt(p.id)}</span> },
      { header: '故障', align: 'right', cell: (p) => (
        cntFault(p.id) > 0
          ? <Badge tone="rose">{cntFault(p.id)}</Badge>
          : <span className="text-ink-300">—</span>
      )},
      { header: '参考价', align: 'right', cell: (p) => <span className="font-mono text-sm">{fmtCurrency(p.list_price)}</span> },
    ];

    return (
      <ListShell
        mobile={mobile}
        title="设备型号"
        hint={`${device_products.length} 个型号 · ${device_units.length} 台在管`}
        items={device_products}
        searchKeys={['name','model','brand']}
        searchPlaceholder="搜型号 / 品牌"
        columns={columns}
        onRow={(p) => navigate(`#/devices/units?product=${p.id}`)}
        primaryAction={<Button size="sm" icon={Icon.plus}>新建型号</Button>}
        archivedKey="_archived"
        mobileItem={(p) => (
          <li key={p.id} onClick={() => navigate(`#/devices/units?product=${p.id}`)}
            className="px-3 py-3 flex items-center gap-3 active:bg-ink-50">
            <span className="h-10 w-10 rounded-md stripe-bg ring-1 ring-ink-200 flex items-center justify-center shrink-0">
              <Icon.cpu size={15} className="text-ink-400" />
            </span>
            <div className="flex-1 min-w-0">
              <div className="text-sm font-medium truncate">{p.name}</div>
              <div className="text-xs text-ink-500 truncate font-mono">{p.brand} · {p.model}</div>
              <div className="text-[11px] text-ink-600 mt-1">
                {cnt(p.id)} 台 · {cntFault(p.id) > 0 ? <span className="text-rose-700">{cntFault(p.id)} 故障</span> : '正常'}
              </div>
            </div>
            <Icon.chevRight size={14} className="text-ink-300 shrink-0" />
          </li>
        )}
        filters={[
          { id: 'category', label: '类别', options: [...new Set(device_products.map(p=>p.category))].map(c => ({ value: c, label: c })), predicate: (r,v) => r.category === v },
        ]}
      />
    );
  }

  /* ---------- Device Units list ---------- */
  function DeviceUnits({ mobile }) {
    const store = useStore();
    const { device_units, device_products, customers, suppliers } = store;
    const productFilter = (window.location.hash.match(/product=([^&]+)/) || [])[1];

    const holderLabel = (h) => {
      if (!h) return 'FB';
      if (h.kind === 'fb') return '🏭 FB 总仓';
      if (h.kind === 'customer') return '🏥 ' + (customers.find(c=>c.id===h.id)?.short || '?');
      if (h.kind === 'supplier') return '🔧 ' + (suppliers.find(s=>s.id===h.id)?.short || '?');
      return '—';
    };

    const rows = device_units.map((u) => {
      const product = device_products.find(p => p.id === u.product_id);
      const alarms = window.deviceAlarms(u);
      return { ...u, _product: product, _alarms: alarms };
    }).filter(u => !productFilter || u.product_id === productFilter);

    const statusTone = (s) => ({ IN_STOCK: 'green', AT_CUSTOMER: 'blue', FAULT: 'rose' })[s];
    const statusLabel = (s) => ({ IN_STOCK: '在库', AT_CUSTOMER: '在客户处', FAULT: '故障' })[s];

    const columns = [
      { header: 'SN / 状态', cell: (u) => (
        <div className="flex items-center gap-2">
          {u.has_sn ? (
            <span className="font-mono text-sm">{u.sn}</span>
          ) : (
            <span className="inline-flex items-center gap-1 text-xs px-1.5 py-0.5 rounded-md bg-amber-50 text-amber-800 ring-1 ring-amber-200 font-medium">
              <Icon.alert size={11} /> SN 缺失
            </span>
          )}
        </div>
      )},
      { header: '型号', cell: (u) => (
        <div>
          <div className="text-sm font-medium truncate">{u._product?.name}</div>
          <div className="text-xs text-ink-500 truncate font-mono">{u._product?.brand} · {u._product?.model}</div>
        </div>
      )},
      { header: '当前位置', cell: (u) => <span className="text-sm">{holderLabel(u.cur_holder)}</span> },
      { header: '状态', cell: (u) => <Badge tone={statusTone(u.status)}>{statusLabel(u.status)}</Badge> },
      { header: '采购 / 保修', cell: (u) => (
        <div>
          <div className="font-mono text-xs">{fmtDate(u.purchased)}</div>
          <div className="text-[11px] text-ink-500">保修至 {fmtDate(u.warranty_until)}</div>
        </div>
      )},
      { header: '报警', cell: (u) => u._alarms.length === 0
        ? <span className="text-[11px] text-ink-300">—</span>
        : <div className="flex flex-wrap gap-1">{u._alarms.map((a, i) => <AlarmChip key={i} type={a.type} />)}</div>
      },
    ];

    return (
      <ListShell
        mobile={mobile}
        title="设备列表"
        hint={`${rows.length} 台 · ${rows.filter(u=>!u.has_sn).length} 台 SN 缺失`}
        items={rows}
        searchKeys={['sn']}
        searchPlaceholder="搜 SN / 序列号"
        columns={columns}
        onRow={(u) => navigate(`#/devices/units/${u.id}`)}
        primaryAction={
          <div className="flex gap-2">
            <Button variant="secondary" size="sm" icon={Icon.truck} onClick={() => navigate('#/devices/transfer/new')}>新转移</Button>
            <Button size="sm" icon={Icon.plus} onClick={() => navigate('#/devices/units/new')}>登记新设备</Button>
          </div>
        }
        archivedKey="_archived"
        mobileItem={(u) => (
          <li key={u.id} onClick={() => navigate(`#/devices/units/${u.id}`)}
            className="px-3 py-3 active:bg-ink-50">
            <div className="flex items-center gap-2 mb-1">
              {u.has_sn ? (
                <span className="font-mono text-sm">{u.sn}</span>
              ) : (
                <Badge tone="amber"><Icon.alert size={10} className="mr-0.5" /> SN 缺失</Badge>
              )}
              <Badge tone={statusTone(u.status)} className="ml-auto">{statusLabel(u.status)}</Badge>
              <Icon.chevRight size={14} className="text-ink-300" />
            </div>
            <div className="text-sm">{u._product?.name}</div>
            <div className="text-xs text-ink-500 mt-0.5">{holderLabel(u.cur_holder)}</div>
            {u._alarms.length > 0 && (
              <div className="flex flex-wrap gap-1 mt-1.5">
                {u._alarms.map((a, i) => <AlarmChip key={i} type={a.type} />)}
              </div>
            )}
          </li>
        )}
        filters={[
          { id: 'status', label: '状态', options: [
            { value: 'IN_STOCK',    label: '在库 (FB)',  count: rows.filter(u=>u.status==='IN_STOCK').length },
            { value: 'AT_CUSTOMER', label: '在客户处',   count: rows.filter(u=>u.status==='AT_CUSTOMER').length },
            { value: 'FAULT',       label: '故障 / 维修', count: rows.filter(u=>u.status==='FAULT').length },
          ], predicate: (r,v) => r.status === v },
          { id: 'sn', label: 'SN 完整性', options: [
            { value: 'missing', label: '⚠️ 缺失', count: rows.filter(u=>!u.has_sn).length },
            { value: 'has',     label: '已登记', count: rows.filter(u=>u.has_sn).length },
          ], predicate: (r,v) => v === 'missing' ? !r.has_sn : r.has_sn },
        ]}
      />
    );
  }

  /* ---------- Unit Detail with Timeline ⭐ ---------- */
  function DeviceUnitDetail({ id, mobile }) {
    const store = useStore();
    const u = store.device_units.find((x) => x.id === id);
    const [tab, setTab] = React.useState('timeline');
    if (!u) return <EmptyState title="未找到该设备" />;
    const p = store.device_products.find((x) => x.id === u.product_id);
    const alarms = window.deviceAlarms(u);

    const transfers = store.device_transfers
      .filter((t) => t.unit_id === id)
      .sort((a, b) => new Date(a.date) - new Date(b.date));

    const holderLabel = (h) => {
      if (!h) return { label: 'FB', kind: 'fb', tone: 'bg-ink-900 text-white' };
      if (h.kind === 'fb') return { label: 'FB', kind: 'fb', tone: 'bg-ink-900 text-white' };
      if (h.kind === 'customer') return { label: store.customers.find(c=>c.id===h.id)?.short || '?', kind: 'customer', tone: 'bg-emerald-100 text-emerald-700 ring-2 ring-emerald-300', full: store.customers.find(c=>c.id===h.id) };
      if (h.kind === 'supplier') return { label: store.suppliers.find(s=>s.id===h.id)?.short || '?', kind: 'supplier', tone: 'bg-rose-100 text-rose-700 ring-2 ring-rose-300', full: store.suppliers.find(s=>s.id===h.id) };
    };

    // Build chain: [FB or origin] → t1.to → t2.to → ... → current
    const chain = [];
    if (transfers.length > 0) chain.push(transfers[0].from);
    for (const t of transfers) chain.push(t.to);
    if (chain.length === 0) chain.push({ kind: 'fb', id: null });

    const statusTone = (s) => ({ IN_STOCK: 'green', AT_CUSTOMER: 'blue', FAULT: 'rose' })[s];
    const statusLabel = (s) => ({ IN_STOCK: '在库 (FB)', AT_CUSTOMER: '在客户处', FAULT: '故障' })[s];

    return (
      <div>
        <div className={cls('bg-white border-b border-ink-100', mobile ? 'p-3' : 'p-6')}>
          <div className="flex items-center gap-2 text-xs text-ink-500 mb-2">
            <button onClick={() => navigate('#/devices/units')} className="hover:text-ink-900">设备列表</button>
            <Icon.chevRight size={11} />
            <span className="text-ink-900 truncate">{u.sn || '(SN 缺失)'}</span>
          </div>
          <div className="flex items-start justify-between gap-3 flex-wrap">
            <div className="min-w-0">
              <div className="flex items-center gap-3 flex-wrap">
                {u.has_sn ? (
                  <h1 className="text-xl font-semibold tracking-tight font-mono">{u.sn}</h1>
                ) : (
                  <h1 className="text-xl font-semibold tracking-tight">
                    <Badge tone="amber" className="text-sm py-1 px-2"><Icon.alert size={12} className="mr-1" />SN 缺失</Badge>
                  </h1>
                )}
                <Badge tone={statusTone(u.status)}>{statusLabel(u.status)}</Badge>
                {alarms.map((a, i) => <AlarmChip key={i} type={a.type} detail={a.detail} size="md" />)}
              </div>
              <div className="text-sm text-ink-700 mt-1.5">{p?.name} <span className="text-ink-400 font-mono">· {p?.brand} {p?.model}</span></div>
              <div className="text-xs text-ink-500 mt-0.5 flex flex-wrap items-center gap-x-3 gap-y-0.5">
                <span>采购 {fmtDate(u.purchased)}</span>
                <span>·</span><span>保修至 {fmtDate(u.warranty_until)}</span>
                <span>·</span><span>{transfers.length} 次转移</span>
              </div>
            </div>
            <div className="flex items-center gap-2 shrink-0">
              <Button variant="secondary" size="sm" icon={Icon.truck} onClick={() => navigate(`#/devices/transfer/new?unit=${u.id}`)}>转移</Button>
              {u.status !== 'FAULT' && <Button variant="secondary" size="sm" icon={Icon.tool}>标记故障</Button>}
              {u.status === 'FAULT' && <Button variant="secondary" size="sm" icon={Icon.check}>标记修复</Button>}
              <IconBtn icon={Icon.moreH} label="更多" variant="outline" />
            </div>
          </div>
          <div className="mt-4">
            <Tabs tabs={[
              { id: 'timeline', label: '转移时间轴', count: transfers.length },
              { id: 'overview', label: '设备信息' },
              { id: 'attach', label: '附件' },
            ]} active={tab} onChange={setTab} />
          </div>
        </div>

        <div className={cls(mobile ? 'p-3' : 'p-6')}>
          {tab === 'timeline' && (
            <>
              {/* Horizontal chain summary */}
              <Card className="p-6 mb-4 overflow-hidden">
                <div className="text-[10px] uppercase tracking-wider text-ink-500 mb-4">转移链 · {chain.length} 跳</div>
                <HChain chain={chain} holderLabel={holderLabel} status={u.status} fault={u.status === 'FAULT'} />
              </Card>

              {/* Vertical detail list */}
              <Card className="p-6">
                <div className="text-[10px] uppercase tracking-wider text-ink-500 mb-3">完整事件列表</div>
                <TransferList transfers={transfers} unit={u} holderLabel={holderLabel} users={store.users} />
              </Card>
            </>
          )}

          {tab === 'overview' && (
            <div className={cls('grid gap-4', mobile ? 'grid-cols-1' : 'grid-cols-3')}>
              <Card className="p-5 col-span-2">
                <h3 className="text-sm font-semibold mb-3">设备信息</h3>
                <dl className="grid grid-cols-2 gap-x-6 gap-y-3 text-sm">
                  <KV label="序列号 (SN)" v={u.has_sn ? <span className="font-mono">{u.sn}</span> : <Badge tone="amber">缺失</Badge>} />
                  <KV label="型号" v={<>{p?.name} <span className="text-ink-400 text-xs">({p?.model})</span></>} />
                  <KV label="厂家" v={p?.brand} />
                  <KV label="采购日期" v={<span className="font-mono">{fmtDate(u.purchased)}</span>} />
                  <KV label="保修截止" v={<span className="font-mono">{fmtDate(u.warranty_until)}</span>} />
                  <KV label="参考价" v={fmtCurrency(p?.list_price)} />
                </dl>
                {u.fault_note && (
                  <div className="mt-4 px-3 py-2.5 rounded-md bg-rose-50 ring-1 ring-rose-200">
                    <div className="text-[11px] uppercase tracking-wider text-rose-700 mb-0.5 flex items-center gap-1">
                      <Icon.tool size={11} /> 故障记录
                    </div>
                    <div className="text-sm text-rose-900">{u.fault_note}</div>
                    {u.sent_to_repair_at && (
                      <div className="text-xs text-rose-700 mt-1">送修于 {fmtDate(u.sent_to_repair_at)} · {fmtRel(u.sent_to_repair_at)}</div>
                    )}
                  </div>
                )}
              </Card>
              <Card className="p-5">
                <h3 className="text-sm font-semibold mb-3">当前持有</h3>
                <CurrentHolder holder={u.cur_holder} store={store} />
              </Card>
            </div>
          )}

          {tab === 'attach' && (
            <Card className="p-6">
              <EmptyState title="暂无附件" hint="可上传保修单、维修单、购买发票等" action={<Button size="sm" icon={Icon.plus}>上传</Button>} />
            </Card>
          )}
        </div>
      </div>
    );
  }

  function CurrentHolder({ holder, store }) {
    if (!holder || holder.kind === 'fb') {
      return (
        <div className="flex items-center gap-3">
          <span className="h-12 w-12 rounded-lg bg-ink-900 text-white inline-flex items-center justify-center font-mono text-xs font-semibold">FB</span>
          <div>
            <div className="text-sm font-medium">FB 总仓</div>
            <div className="text-xs text-ink-500">实验仓 · 待出库</div>
          </div>
        </div>
      );
    }
    if (holder.kind === 'customer') {
      const c = store.customers.find(x => x.id === holder.id);
      return (
        <div>
          <div className="flex items-center gap-3 mb-3">
            <span className="h-12 w-12 rounded-lg bg-emerald-100 text-emerald-700 inline-flex items-center justify-center font-semibold">{c?.short?.slice(0,2)}</span>
            <div>
              <button onClick={() => navigate(`#/customers/${c?.id}`)} className="text-sm font-medium hover:underline">{c?.name}</button>
              <div className="text-xs text-ink-500">{c?.city} · {c?.contact}</div>
            </div>
          </div>
          <Button variant="secondary" size="xs" icon={Icon.arrowR} onClick={() => navigate(`#/devices/transfer/new?unit=${''}`)}>转移至其它客户</Button>
        </div>
      );
    }
    if (holder.kind === 'supplier') {
      const s = store.suppliers.find(x => x.id === holder.id);
      return (
        <div className="flex items-center gap-3">
          <span className="h-12 w-12 rounded-lg bg-rose-100 text-rose-700 inline-flex items-center justify-center">
            <Icon.tool size={18} />
          </span>
          <div>
            <div className="text-sm font-medium">{s?.name}</div>
            <div className="text-xs text-rose-700">送修中</div>
          </div>
        </div>
      );
    }
    return null;
  }

  /* Horizontal chain viz */
  function HChain({ chain, holderLabel, fault }) {
    return (
      <div className="overflow-x-auto pb-2 -mx-2 px-2">
        <div className="flex items-center min-w-min" style={{ minWidth: chain.length * 130 }}>
          {chain.map((h, i) => {
            const meta = holderLabel(h);
            const isLast = i === chain.length - 1;
            return (
              <React.Fragment key={i}>
                <div className="flex flex-col items-center shrink-0" style={{ minWidth: 110 }}>
                  <div className={cls(
                    'h-12 w-12 rounded-2xl flex items-center justify-center font-mono text-[11px] font-semibold relative',
                    meta.tone,
                    isLast && fault && 'pulse-rose',
                    isLast && !fault && 'ring-4 ring-emerald-200'
                  )}>
                    {meta.label.slice(0, 2)}
                    {isLast && (
                      <span className="absolute -top-1 -right-1 h-3 w-3 rounded-full bg-emerald-500 ring-2 ring-white"></span>
                    )}
                  </div>
                  <div className="mt-2 text-[11px] font-medium text-center max-w-[110px] truncate">{meta.label}</div>
                  <div className="text-[10px] text-ink-400">{
                    meta.kind === 'fb' ? '总仓' :
                    meta.kind === 'customer' ? '客户' : '供货商'
                  }</div>
                </div>
                {!isLast && (
                  <div className="flex flex-col items-center shrink-0 mb-6" style={{ width: 60 }}>
                    <Icon.arrowR size={14} className="text-ink-400" />
                  </div>
                )}
              </React.Fragment>
            );
          })}
        </div>
      </div>
    );
  }

  function TransferList({ transfers, unit, holderLabel, users }) {
    if (transfers.length === 0) {
      return <EmptyState title="尚无转移记录" hint="设备登记后会自动记录一条初始入库" />;
    }
    return (
      <ol className="relative">
        <div className="absolute left-[15px] top-2 bottom-2 w-px bg-ink-200"></div>
        {transfers.map((t, i) => {
          const from = holderLabel(t.from), to = holderLabel(t.to);
          const user = users.find(u => u.id === t.by_user);
          return (
            <li key={t.id} className="relative pl-10 pb-5 last:pb-0">
              <span className="absolute left-0 top-0 h-8 w-8 rounded-full bg-violet-100 text-violet-700 ring-2 ring-white inline-flex items-center justify-center">
                <Icon.truck size={14} />
              </span>
              <div className="flex items-baseline justify-between gap-3 flex-wrap">
                <div className="text-sm flex items-center gap-2 flex-wrap">
                  <span className={cls('px-1.5 py-0.5 rounded font-mono text-[11px]', from.tone)}>{from.label}</span>
                  <Icon.arrowR size={13} className="text-ink-400" />
                  <span className={cls('px-1.5 py-0.5 rounded font-mono text-[11px]', to.tone)}>{to.label}</span>
                </div>
                <div className="text-xs text-ink-500 font-mono shrink-0">
                  {fmtDate(t.date)} <span className="text-ink-400">· {fmtRel(t.date)}</span>
                </div>
              </div>
              <div className="text-xs text-ink-600 mt-1">
                {t.note ? t.note : <span className="text-ink-400 italic">无备注</span>}
              </div>
              <div className="text-[11px] text-ink-400 mt-0.5">由 {user?.name} 操作</div>
            </li>
          );
        })}
      </ol>
    );
  }

  /* ---------- New Unit form ---------- */
  function DeviceUnitNew({ mobile }) {
    const store = useStore();
    const [form, setForm] = React.useState({
      product_id: '', sn: '', has_sn: true,
      purchased: '2026-05-28', warranty_until: '2028-05-28',
      notes: '',
    });
    const set = (k) => (v) => setForm({ ...form, [k]: v });
    const setI = (k) => (e) => setForm({ ...form, [k]: e.target.value });
    const ok = form.product_id && (form.has_sn ? form.sn : true);

    const submit = (next) => {
      if (!ok) return;
      const id = window.nextId('du');
      const row = {
        id, product_id: form.product_id, sn: form.has_sn ? form.sn : null, has_sn: form.has_sn,
        purchased: form.purchased, warranty_until: form.warranty_until,
        status: 'IN_STOCK', cur_holder: { kind: 'fb', id: null }, fault_note: null, sent_to_repair_at: null,
      };
      store.add('device_units', row);
      const p = store.device_products.find(p => p.id === form.product_id);
      store.toast(`已登记 ${p?.name} ${form.has_sn ? form.sn : '(SN 缺失)'}`);
      store.logActivity({ kind: 'receive', text: `登记新设备 ${p?.name} · ${form.has_sn ? form.sn : 'SN 待补'}`, ref: id });
      if (next) setForm({ ...form, sn: '' });
      else navigate(`#/devices/units/${id}`);
    };

    return (
      <FormShell mobile={mobile} title="登记新设备" hint="按 SN 唯一管理 · 没有 SN 可暂时勾选「SN 缺失」"
        crumb={[{ label: '设备列表', to: '#/devices/units' }, { label: '登记' }]}
        actions={
          <>
            <Button variant="ghost" size="sm" onClick={() => navigate('#/devices/units')}>取消</Button>
            <Button variant="secondary" size="sm" disabled={!ok} onClick={() => submit(true)}>保存并新建</Button>
            <Button size="sm" disabled={!ok} onClick={() => submit(false)} icon={Icon.check}>登记</Button>
          </>
        }>
        <div className={cls('grid gap-x-4 gap-y-4', mobile ? 'grid-cols-1' : 'grid-cols-2')}>
          <Field label="设备型号" required className={cls(!mobile && 'col-span-2')}>
            <SearchableSelect
              options={store.device_products.map(p => ({ id: p.id, label: p.name, sub: `${p.brand} · ${p.model}` }))}
              value={form.product_id}
              onChange={set('product_id')}
              recentIds={['dp-1','dp-3']} required={!form.product_id}
              placeholder="搜型号 / 品牌" />
          </Field>
          <Field label="序列号 (SN)" required={form.has_sn} className={cls(!mobile && 'col-span-2')}>
            <Input value={form.sn} onChange={setI('sn')} disabled={!form.has_sn}
              placeholder="例：5810R-2024-0091" className="font-mono" required={form.has_sn && !form.sn} />
            <label className="flex items-center gap-1.5 mt-1.5 text-xs text-ink-600">
              <input type="checkbox" checked={!form.has_sn}
                onChange={(e) => setForm({ ...form, has_sn: !e.target.checked })}
                className="rounded ring-1 ring-ink-300" />
              <Icon.alert size={11} className="text-amber-600" />
              SN 暂缺 — 稍后补登（会在列表显示「SN 缺失」徽章）
            </label>
          </Field>
          <Field label="采购日期"><DateField value={form.purchased} onChange={set('purchased')} /></Field>
          <Field label="保修截止"><DateField value={form.warranty_until} onChange={set('warranty_until')} /></Field>
          <Field label="备注" className={cls(!mobile && 'col-span-2')}>
            <Textarea value={form.notes} onChange={setI('notes')} placeholder="可选" />
          </Field>
        </div>
      </FormShell>
    );
  }

  /* ---------- New Transfer ⭐ ---------- */
  function DeviceTransferNew({ mobile }) {
    const store = useStore();
    const params = new URLSearchParams(window.location.hash.split('?')[1] || '');
    const initUnit = params.get('unit') || '';
    const initTo = params.get('to') || '';

    const [form, setForm] = React.useState({
      unit_id: initUnit,
      to_kind: initTo ? 'customer' : '',     // 'fb' | 'customer' | 'supplier'
      to_id: initTo,
      date: '2026-05-28',
      note: '',
    });
    const [custModal, setCustModal] = React.useState(false);
    const [supModal, setSupModal] = React.useState(false);
    const set = (k) => (v) => setForm({ ...form, [k]: v });
    const setI = (k) => (e) => setForm({ ...form, [k]: e.target.value });

    const unit = store.device_units.find(u => u.id === form.unit_id);
    const product = unit ? store.device_products.find(p => p.id === unit.product_id) : null;
    const from = unit?.cur_holder || { kind: 'fb', id: null };

    const targetOptions = form.to_kind === 'customer'
      ? store.customers.filter(c=>!c.archived).map(c => ({ id: c.id, label: c.name, sub: `${c.city} · ${c.tags?.join(' / ')}` }))
      : form.to_kind === 'supplier'
      ? store.suppliers.filter(s=>!s.archived).map(s => ({ id: s.id, label: s.name, sub: `${s.city} · 适用于送修` }))
      : [];

    const target = form.to_kind === 'fb' ? null
      : form.to_kind === 'customer' ? store.customers.find(c => c.id === form.to_id)
      : store.suppliers.find(s => s.id === form.to_id);

    const ok = form.unit_id && form.to_kind && (form.to_kind === 'fb' || form.to_id);

    const submit = (next) => {
      if (!ok) return;
      const id = window.nextId('dt');
      const to = form.to_kind === 'fb' ? { kind: 'fb', id: null } : { kind: form.to_kind, id: form.to_id };
      const row = { id, unit_id: form.unit_id, from, to, date: form.date, by_user: store.currentUserId, note: form.note };
      store.add('device_transfers', row);
      // update unit holder + status
      let newStatus = unit.status;
      if (to.kind === 'fb') newStatus = unit.status === 'FAULT' ? 'FAULT' : 'IN_STOCK';
      else if (to.kind === 'customer') newStatus = 'AT_CUSTOMER';
      else if (to.kind === 'supplier') newStatus = 'FAULT';
      store.update('device_units', form.unit_id, {
        cur_holder: to, status: newStatus,
        sent_to_repair_at: to.kind === 'supplier' ? form.date : unit.sent_to_repair_at,
      });
      const labelTo = to.kind === 'fb' ? 'FB 总仓' : (target?.short || target?.name);
      store.toast(`已转移 ${unit.sn || product?.name} → ${labelTo}`);
      store.logActivity({ kind: 'transfer', text: `转移设备 ${unit.sn || product?.name} → ${labelTo}`, ref: form.unit_id });
      if (next) setForm({ unit_id: '', to_kind: '', to_id: '', date: form.date, note: '' });
      else navigate(`#/devices/units/${form.unit_id}`);
    };

    const holderName = (h) => {
      if (!h || h.kind === 'fb') return 'FB 总仓';
      if (h.kind === 'customer') return store.customers.find(c=>c.id===h.id)?.short || '?';
      if (h.kind === 'supplier') return store.suppliers.find(s=>s.id===h.id)?.short || '?';
    };
    const holderTone = (h) => {
      if (!h || h.kind === 'fb') return 'bg-ink-900 text-white';
      if (h.kind === 'customer') return 'bg-emerald-100 text-emerald-800 ring-1 ring-emerald-300';
      if (h.kind === 'supplier') return 'bg-rose-100 text-rose-800 ring-1 ring-rose-300';
    };

    return (
      <>
        <FormShell mobile={mobile} title="新转移" hint="⭐ 多跳转移链 · FB → 客户 → 客户 → FB → 供货商（送修）"
          crumb={[{ label: '设备列表', to: '#/devices/units' }, { label: '新转移' }]}
          actions={
            <>
              <Button variant="ghost" size="sm" onClick={() => navigate('#/devices/units')}>取消</Button>
              <Button variant="secondary" size="sm" disabled={!ok} onClick={() => submit(true)}>保存并新建</Button>
              <Button size="sm" disabled={!ok} onClick={() => submit(false)} icon={Icon.check}>确认转移</Button>
            </>
          }>
          <div className={cls('grid gap-4', mobile ? 'grid-cols-1' : 'grid-cols-3')}>
            <div className={cls(mobile ? '' : 'col-span-2')}>
              <div className="grid gap-x-4 gap-y-4 grid-cols-2">
                <Field label="设备 (SN)" required className="col-span-2">
                  <SearchableSelect
                    options={store.device_units.map(u => {
                      const p = store.device_products.find(p => p.id === u.product_id);
                      return { id: u.id, label: u.sn || `${p?.name} (SN 缺失)`, sub: `${p?.name} · ${holderName(u.cur_holder)} · ${u.status}`, _u: u };
                    })}
                    value={form.unit_id}
                    onChange={set('unit_id')}
                    recentIds={['du-1','du-3']}
                    required={!form.unit_id}
                    placeholder="搜 SN / 型号"
                    renderOption={(o) => (
                      <>
                        <div className="flex-1 min-w-0">
                          <div className="font-mono text-sm">{o._u.sn || <Badge tone="amber">SN 缺失</Badge>}</div>
                          <div className="text-xs text-ink-500">{o.sub}</div>
                        </div>
                      </>
                    )}
                  />
                </Field>

                <Field label="目标类型" required>
                  <div className="flex gap-1.5">
                    {[
                      { id: 'fb',       label: '🏭 FB 总仓',   hint: '回库' },
                      { id: 'customer', label: '🏥 客户',     hint: '配置 / 转借' },
                      { id: 'supplier', label: '🔧 供货商',   hint: '送修' },
                    ].map(o => (
                      <button key={o.id} type="button"
                        onClick={() => setForm({ ...form, to_kind: o.id, to_id: '' })}
                        className={cls(
                          'flex-1 h-16 px-3 rounded-lg ring-1 text-left text-sm flex flex-col justify-center',
                          form.to_kind === o.id ? 'bg-ink-900 text-white ring-ink-900' : 'bg-white text-ink-700 ring-ink-200 hover:bg-ink-50'
                        )}>
                        <div className="font-medium">{o.label}</div>
                        <div className={cls('text-[11px]', form.to_kind === o.id ? 'text-ink-300' : 'text-ink-500')}>{o.hint}</div>
                      </button>
                    ))}
                  </div>
                </Field>

                {form.to_kind !== 'fb' && (
                  <Field label={form.to_kind === 'supplier' ? '送修至供货商' : '目标客户'} required>
                    <SearchableSelect
                      options={targetOptions}
                      value={form.to_id}
                      onChange={set('to_id')}
                      recentIds={form.to_kind === 'customer' ? ['c-1','c-3'] : ['s-4','s-2']}
                      allowCreate
                      onCreate={() => form.to_kind === 'customer' ? setCustModal(true) : setSupModal(true)}
                      required={!form.to_id}
                      placeholder={`搜 ${form.to_kind === 'customer' ? '客户' : '供货商'} — 找不到？「即时新建」`} />
                  </Field>
                )}
                {form.to_kind === 'fb' && <div></div>}

                <Field label="转移日期" required><DateField value={form.date} onChange={set('date')} /></Field>
                <Field label="备注" className="col-span-2">
                  <Textarea value={form.note} onChange={setI('note')}
                    placeholder={form.to_kind === 'supplier' ? '故障描述 / 维修要求' : '可选'} />
                </Field>
              </div>
            </div>

            {/* Right preview */}
            <Card className="p-5 self-start bg-ink-50/40 ring-ink-200">
              <div className="text-[10px] uppercase tracking-wider text-ink-500 mb-2">转移预览</div>
              {!unit ? (
                <div className="text-sm text-ink-400 italic">尚未选择设备</div>
              ) : (
                <>
                  <div className="text-sm font-medium leading-snug">{product?.name}</div>
                  <div className="text-xs text-ink-500 font-mono mt-0.5">{unit.sn || 'SN 缺失'}</div>

                  <div className="mt-4 p-4 bg-white rounded-lg ring-1 ring-ink-200">
                    <div className="flex items-center justify-between gap-2">
                      <div className="text-center flex-1 min-w-0">
                        <div className={cls('h-12 w-12 rounded-2xl mx-auto inline-flex items-center justify-center font-mono text-[11px] font-semibold',
                          holderTone(from))}>
                          {holderName(from).slice(0, 2)}
                        </div>
                        <div className="text-[10px] uppercase tracking-wider text-ink-400 mt-1.5">现位置</div>
                        <div className="text-xs font-medium truncate mt-0.5">{holderName(from)}</div>
                      </div>
                      <Icon.arrowR size={18} className="text-ink-400 shrink-0" />
                      <div className="text-center flex-1 min-w-0">
                        {form.to_kind ? (
                          <>
                            <div className={cls('h-12 w-12 rounded-2xl mx-auto inline-flex items-center justify-center font-mono text-[11px] font-semibold ring-4 ring-emerald-200',
                              holderTone(form.to_kind === 'fb' ? { kind: 'fb' } : { kind: form.to_kind, id: form.to_id }))}>
                              {(form.to_kind === 'fb' ? 'FB' : (target?.short || target?.name || '?')).slice(0, 2)}
                            </div>
                            <div className="text-[10px] uppercase tracking-wider text-ink-400 mt-1.5">目标</div>
                            <div className="text-xs font-medium truncate mt-0.5">{form.to_kind === 'fb' ? 'FB 总仓' : (target?.short || target?.name || '待选择')}</div>
                          </>
                        ) : (
                          <>
                            <div className="h-12 w-12 rounded-2xl mx-auto inline-flex items-center justify-center font-mono text-xl text-ink-300 ring-2 ring-dashed ring-ink-300">?</div>
                            <div className="text-[10px] uppercase tracking-wider text-ink-400 mt-1.5">目标</div>
                            <div className="text-xs text-ink-400 mt-0.5">未选择</div>
                          </>
                        )}
                      </div>
                    </div>
                  </div>

                  {form.to_kind === 'supplier' && (
                    <div className="mt-3 px-2.5 py-2 rounded-md bg-rose-50 ring-1 ring-rose-200 text-xs text-rose-700">
                      🔧 设备状态将自动标记为「故障·送修中」<br />超过 60 天未归会触发 🟣 修复超期
                    </div>
                  )}
                  {form.to_kind === 'fb' && unit.status === 'AT_CUSTOMER' && (
                    <div className="mt-3 px-2.5 py-2 rounded-md bg-sky-50 ring-1 ring-sky-200 text-xs text-sky-700">
                      回库后状态将变为「在库 (FB)」
                    </div>
                  )}
                </>
              )}
            </Card>
          </div>
        </FormShell>

        <Modal open={custModal} onClose={() => setCustModal(false)} size="lg" title="即时新建客户">
          <CustomerNew isModal onCreated={(c) => { setForm({ ...form, to_id: c.id }); setCustModal(false); }} onCancel={() => setCustModal(false)} />
        </Modal>
        <Modal open={supModal} onClose={() => setSupModal(false)} size="lg" title="即时新建供货商">
          <SupplierNew isModal onCreated={(s) => { setForm({ ...form, to_id: s.id }); setSupModal(false); }} onCancel={() => setSupModal(false)} />
        </Modal>
      </>
    );
  }

  Object.assign(window, { DeviceProducts, DeviceUnits, DeviceUnitDetail, DeviceUnitNew, DeviceTransferNew });
})();
