/* ==========================================================================
 * ADMIN NEXT — page-finance.jsx  (แยกจาก index.html เดิม; โหลดผ่าน <script type="text/babel">)
 * โหลดตามลำดับใน index.html — ทุกไฟล์แชร์ scope เดียวกัน (babel-standalone)
 * ========================================================================== */
function withdrawalNeedsWalletAccount(row) {
  let meta=row&&row.meta;
  if(typeof meta==="string"){ try{meta=JSON.parse(meta);}catch{meta={};} }
  const dest=String((row&&row.corrected_bank_code)||row?.bank_code||"").toLowerCase();
  return dest==="truewallet"||meta?.withdrawMethod==="wallet"||meta?.destinationType==="wallet";
}
function parseWithdrawMeta(row) {
  let meta=row&&row.meta;
  if(typeof meta==="string"){ try{meta=JSON.parse(meta);}catch{meta={};} }
  return meta||{};
}
/* พอร์ตจาก withdrawTypeLabel ของแอดมินเดิม */
function withdrawTypeLabel(row) {
  const meta=parseWithdrawMeta(row);
  const raw=String(row.withdraw_type||row.type||meta.withdraw_type||meta.withdrawMethod||"").toLowerCase();
  if(raw==="wallet"||withdrawalNeedsWalletAccount(row)) return "ถอน TrueWallet (TMNOne)";
  return ({ bank:"ถอนธนาคาร", manual:"ถอน Manual", auto:"ถอนอัตโนมัติ", autopeer:"ถอนธนาคาร (Autopeer)", adb:"ถอนธนาคาร (ABD)",
    max_by_turnover:"ถอนครบเทิร์น", fixed_max_withdraw:"ถอนตามยอดสูงสุด" })[raw] || "ถอนเครดิต";
}
/* ref ของ Autopeer (มีเมื่อส่งรายการถอนไป Autopeer สำเร็จตอนลูกค้ายื่นถอน) — เก็บแบบไม่มี AP_ */
function withdrawAutopeerRef(row) {
  const ref = row.channel==="autopeer" && row.ref_id ? row.ref_id : parseWithdrawMeta(row).autopeerRef;
  return ref ? String(ref).replace(/^AP_/,"") : "";
}
const bahtNum = (n)=>Number(n).toLocaleString("th-TH",{minimumFractionDigits:2,maximumFractionDigits:2});
/* ยอดจาก Autopeer เป็นบาท: peer โอนให้ลูกค้าแล้วเท่าไร จากยอดที่ต้องโอนทั้งหมด */
function autopeerProgressText(p) {
  if (!p || p.paid==null || !p.total) return "";
  return "โอนแล้ว "+bahtNum(p.paid)+" / ต้องโอน "+bahtNum(p.total);
}
function AutopeerProgress({ p }) {
  const text = autopeerProgressText(p);
  if (!text) return null;
  const done = p.paid >= p.total;
  return <div className={"mt-1 whitespace-nowrap text-[11px] font-semibold tnum "+(done?"text-success":"text-warn")} title={done?"Autopeer โอนครบแล้ว":"Autopeer ยังโอนไม่ครบ — ส่วนที่เหลือต้องจ่ายเอง ถ้ารายการหมดเวลา"}>{text}</div>;
}
function payoutAccountLabel(a) {
  return a.type==="TMNWD"
    ? ["TMN ถอน (TMNWD)",a.wallet_phone,a.account_name].filter(Boolean).join(" · ")
    : [a.bank_name||bankName(a.bank_code),a.account_no,a.account_name].filter(Boolean).join(" · ");
}
function WithdrawalAccountModal({ row, onClose, onDone, toast }) {
  const [accounts,setAccounts]=useState([]),[selected,setSelected]=useState(String(row.payout_account_id||""));
  const [loading,setLoading]=useState(true),[busy,setBusy]=useState(false);
  const wallet=withdrawalNeedsWalletAccount(row);
  useEffect(()=>{ let active=true;
    api("/withdrawal-accounts").then(data=>{if(active)setAccounts((Array.isArray(data)?data:[]).filter(a=>a.is_active&&(wallet?a.type==="TMNWD":a.type!=="TMNWD")));})
      .catch(e=>{if(active)toast(e.message||"โหลดบัญชีถอนไม่สำเร็จ");})
      .finally(()=>{if(active)setLoading(false);});
    return()=>{active=false;};
  },[wallet,toast]);
  const save=async()=>{setBusy(true);
    try{await api("/withdrawals/"+row.id+"/payout-account",{method:"PATCH",body:{accountId:selected||null}});toast("กำหนดบัญชีถอนแล้ว");onDone&&onDone();onClose();}
    catch(e){toast(e.message||"กำหนดบัญชีถอนไม่สำเร็จ");}
    finally{setBusy(false);}
  };
  return (<div className="fixed inset-0 z-[80] flex items-center justify-center p-4 fade-in" onMouseDown={()=>!busy&&onClose()}>
    <div className="absolute inset-0 bg-black/55"/>
    <div className="pop relative w-full max-w-md rounded-2xl border border-line bg-surface2 p-5 shadow-lg" onMouseDown={e=>e.stopPropagation()}>
      <div className="text-base font-semibold">{String(row.status||"").toLowerCase()==="pending"?"ระบุบัญชีถอนเงิน":"ปรับบัญชีถอนย้อนหลัง"}</div>
      <div className="mt-1 text-xs text-muted">ผู้รับเงิน: {row.username||row.full_name||"-"} · {money2(row.amount)}</div>
      {String(row.status||"").toLowerCase()!=="pending" && <div className="mt-2 rounded-lg border border-info/40 bg-info-soft px-3 py-2 text-[11px] leading-relaxed text-fg-2">แก้ไขบัญชีจ่ายของรายการที่จ่ายแล้ว เพื่อให้บันทึกถูกต้อง · เป็นการปรับข้อมูลย้อนหลังเท่านั้น ไม่กระทบยอดเครดิตหรือการโอนจริง</div>}
      {loading ? <div className="skel mt-4 h-10 w-full"/> : accounts.length===0
        ? <div className="mt-4 rounded-lg border border-warn/40 bg-warn-soft p-3 text-sm text-fg-2">ยังไม่มีบัญชีถอนที่ตรงกับประเภทรายการนี้ กรุณาเพิ่มบัญชีที่เมนูธนาคาร &gt; บัญชีถอน</div>
        : <label className="mt-4 block"><span className="text-xs font-medium text-fg-2">บัญชีที่ใช้จ่าย</span>
          <select value={selected} onChange={e=>setSelected(e.target.value)} className="mt-1 h-10 w-full rounded-lg border border-line bg-sunken px-3 text-sm text-fg">
            {!wallet&&<option value="">ไม่ระบุบัญชี</option>}
            {accounts.map(a=><option key={a.id} value={a.id}>{payoutAccountLabel(a)}</option>)}
          </select>
        </label>}
      <div className="mt-5 flex justify-end gap-2">
        <button onClick={onClose} className="h-9 rounded-lg border border-line bg-surface px-3 text-sm font-medium text-fg-2 hover:bg-sunken">ยกเลิก</button>
        <button disabled={busy||loading||accounts.length===0||(wallet&&!selected)} onClick={save} className="h-9 rounded-lg bg-accent px-4 text-sm font-semibold text-accent-fg disabled:opacity-50">{busy?"กำลังบันทึก…":"บันทึกบัญชี"}</button>
      </div>
    </div>
  </div>);
}
/* ---------- รายการถอน: พอร์ตจาก withdrawals.js ของแอดมินเดิม ---------- */
/* ถอนแบบไหน: ปลายทาง TrueWallet = wallet, ไม่ระบุ = adb (เหมือน getWithdrawMethod เดิม) */
function withdrawMethodOf(row) {
  const meta=parseWithdrawMeta(row);
  const dest=String((row&&row.corrected_bank_code)||row?.bank_code||"").toLowerCase();
  if(dest==="truewallet"||meta.withdrawMethod==="wallet"||meta.destinationType==="wallet") return "wallet";
  if(meta.withdrawMethod) return String(meta.withdrawMethod).toLowerCase();
  return "adb";
}
/* บัญชีลูกค้าที่ใช้แสดง: ถ้าแอดมินแก้บัญชีที่ถอนจริงแล้ว ใช้ค่าที่แก้ */
function withdrawDest(row) {
  const fixed=!!row.corrected_account_no;
  return { fixed, code:fixed?row.corrected_bank_code:row.bank_code, no:fixed?row.corrected_account_no:row.bank_account_no, name:fixed?row.corrected_account_name:row.bank_account_name };
}
function withdrawNote(row) {
  const m=parseWithdrawMeta(row);
  return row.tmnone_p2p_note||(m.tmnone&&(m.tmnone.payout_note||m.tmnone.p2p_status_message))||row.note||row.reject_reason||row.reason||m.reason||null;
}
const WD_CORRECT_BANKS=[["KBANK","กสิกร"],["SCB","ไทยพาณิชย์"],["KTB","กรุงไทย"],["BBL","กรุงเทพ"],["BAY","กรุงศรี"],["TTB","ทหารไทยธนชาต"],["GSB","ออมสิน"],["BAAC","ธ.ก.ส."],["GHB","อาคารสงเคราะห์"],["TISCO","ทิสโก้"],["KK","เกียรตินาคิน"],["CIMB","ซีไอเอ็มบี"],["LHB","แลนด์แอนด์เฮ้าส์"]];

function WdModalShell({ title, sub, busy, onClose, children, footer }) {
  return (<div className="fixed inset-0 z-[80] flex items-center justify-center p-4 fade-in" onMouseDown={()=>!busy&&onClose()}>
    <div className="absolute inset-0 bg-black/55"/>
    <div className="pop relative max-h-[90vh] w-full max-w-md overflow-y-auto rounded-2xl border border-line bg-surface2 p-5 shadow-lg" onMouseDown={e=>e.stopPropagation()}>
      <div className="text-base font-semibold">{title}</div>
      {sub&&<div className="mt-1 text-xs text-muted">{sub}</div>}
      {children}
      <div className="mt-5 flex flex-wrap justify-end gap-2">{footer}</div>
    </div>
  </div>);
}
function WdDestBox({ row }) {
  const d=withdrawDest(row); const wallet=withdrawMethodOf(row)==="wallet";
  return (<div className="mt-4 rounded-xl border border-line bg-sunken/60 p-3 text-sm">
    <div className="flex items-center gap-3 border-b border-line-soft pb-2.5">
      <BankLogo code={wallet?"truewallet":d.code} size={36}/>
      <div className="min-w-0">
        <div className="font-semibold">{wallet?"TrueMoney Wallet":(d.code?bankName(d.code):"บัญชีลูกค้า")}</div>
        <div className="mono text-[13px] text-fg-2">{d.no||row.phone||"-"}</div>
        {d.name&&<div className="text-xs text-muted">{d.name}</div>}
      </div>
    </div>
    <div className="mt-2 flex justify-between"><span className="text-muted">ลูกค้า</span><b>{row.username||"-"}</b></div>
    <div className="mt-1 flex justify-between"><span className="text-muted">ยอดถอน</span><b className="text-danger tnum">-{money2(row.amount)}</b></div>
  </div>);
}
/* อนุมัติถอน: เลือกบัญชีที่ใช้จ่าย (ถอนวอลเล็ทต้องเป็น TMNWD) + เครื่อง ABD */
function WithdrawApproveModal({ row, onClose, onDone, toast, notice }) {
  const method=withdrawMethodOf(row); const wallet=method==="wallet";
  const [accounts,setAccounts]=useState([]),[devices,setDevices]=useState([]);
  const [acct,setAcct]=useState(""),[device,setDevice]=useState("");
  const [loading,setLoading]=useState(true),[busy,setBusy]=useState(false);
  useEffect(()=>{ let on=true;
    Promise.all([
      api("/withdrawal-accounts").catch(()=>[]),
      method==="adb"?api("/abd-console/devices").catch(()=>null):Promise.resolve(null),
    ]).then(([accs,dl])=>{ if(!on) return;
      const list=(Array.isArray(accs)?accs:[]).filter(a=>a.is_active&&(wallet?a.type==="TMNWD":(method==="adb"||method==="autopeer"||method==="bank")?a.type!=="TMNWD":true));
      setAccounts(list);
      setAcct(String(row.payout_account_id||(list.length===1?list[0].id:"")));
      setDevices((dl&&Array.isArray(dl.devices))?dl.devices:[]);
    }).finally(()=>{ if(on) setLoading(false); });
    return ()=>{ on=false; };
  },[]);
  const needBankAcct=!wallet&&(method==="adb"||method==="bank");
  const blocked=!loading&&((wallet||needBankAcct)&&accounts.length===0);
  const submit=async()=>{ if(wallet&&!acct) return toast("กรุณาเลือกบัญชี TrueWallet (TMNWD) ที่จะใช้โอน"); setBusy(true);
    try{ await api("/withdrawals/"+row.id+"/approve",{method:"POST",body:{accountId:acct||null,device:device||null}});
      toast(wallet?"อนุมัติและส่งโอน TrueMoney แล้ว":"อนุมัติถอนเงินแล้ว"); onDone&&onDone(); onClose(); }
    catch(e){ toast(e.message||"อนุมัติไม่สำเร็จ"); } finally{ setBusy(false); } };
  return (<WdModalShell title={wallet?"เลือกบัญชี TMNWD และยืนยันอนุมัติ":"เลือกบัญชีและยืนยันอนุมัติ"} busy={busy} onClose={onClose}
    footer={<><button onClick={onClose} disabled={busy} className="h-9 rounded-lg border border-line bg-surface px-3 text-sm font-medium text-fg-2 hover:bg-sunken">ยกเลิก</button>
      <button onClick={submit} disabled={busy||loading||blocked||(wallet&&!acct)} className="h-9 rounded-lg px-4 text-sm font-semibold text-white disabled:opacity-50" style={{background:"var(--success)"}}>{busy?"กำลังอนุมัติ…":"✓ อนุมัติ"}</button></>}>
    <WdDestBox row={row}/>
    {notice}
    {loading ? <div className="skel mt-4 h-10 w-full"/> : blocked
      ? <div className="mt-4 rounded-lg border border-warn/40 bg-warn-soft p-3 text-sm text-fg-2">{wallet?"ยังไม่มีบัญชี TMNWD ในระบบ":"ยังไม่มีบัญชีธนาคารถอนในระบบ"} กรุณาเพิ่มที่เมนู ธนาคาร &gt; บัญชีถอน</div>
      : <label className="mt-4 block"><span className="text-xs font-medium text-fg-2">{wallet?"บัญชี TrueWallet ที่ใช้โอน (TMNWD)":"บัญชีธนาคารถอนออก"}</span>
          <select value={acct} onChange={e=>setAcct(e.target.value)} className="mt-1 h-10 w-full rounded-lg border border-line bg-sunken px-3 text-sm text-fg">
            {!wallet?<option value="">-- เลือกบัญชีธนาคาร --</option>:!acct&&<option value="">-- เลือกบัญชี TMNWD --</option>}
            {accounts.map(a=><option key={a.id} value={a.id}>{payoutAccountLabel(a)}</option>)}
          </select></label>}
    {method==="adb"&&devices.length>0&&<label className="mt-3 block"><span className="text-xs font-medium text-fg-2">เครื่องที่ใช้จ่าย (ABD)</span>
      <select value={device} onChange={e=>setDevice(e.target.value)} className="mt-1 h-10 w-full rounded-lg border border-line bg-sunken px-3 text-sm text-fg">
        <option value="">-- สุ่มเครื่องว่าง --</option>
        {devices.map(d=><option key={d.device_id} value={d.device_id} disabled={!d.online}>{(d.online?"🟢 ":"⚪ ")+(d.custom_label||d.label||d.device_id)+(d.online?"":" (ออฟไลน์)")}</option>)}
      </select></label>}
  </WdModalShell>);
}
/* ปฏิเสธถอน: คืนเครดิต (refund) หรือ ตัดเครดิต (ไม่คืนยอดที่หักไปตอนยื่นถอน) */
function WithdrawRejectModal({ row, onClose, onDone, toast }) {
  const [reason,setReason]=useState(""),[busy,setBusy]=useState(false);
  const submit=async(refund)=>{ setBusy(true);
    try{ await api("/withdrawals/"+row.id+"/reject",{method:"POST",body:{reason:reason.trim()||"rejected",refund}});
      toast(refund?"ปฏิเสธและคืนเครดิตแล้ว":"ปฏิเสธและตัดเครดิตแล้ว"); onDone&&onDone(); onClose(); }
    catch(e){ toast(e.message||"ปฏิเสธไม่สำเร็จ"); } finally{ setBusy(false); } };
  return (<WdModalShell title="ปฏิเสธการถอน" sub={(row.username||row.full_name||"-")+" · "+money2(row.amount)} busy={busy} onClose={onClose}
    footer={<><button onClick={onClose} disabled={busy} className="h-9 rounded-lg border border-line bg-surface px-3 text-sm font-medium text-fg-2 hover:bg-sunken">ยกเลิก</button>
      <button onClick={()=>submit(false)} disabled={busy} className="h-9 rounded-lg px-3 text-sm font-semibold text-white disabled:opacity-50" style={{background:"var(--danger)"}}>ตัดเครดิต</button>
      <button onClick={()=>submit(true)} disabled={busy} className="h-9 rounded-lg bg-accent px-3 text-sm font-semibold text-accent-fg disabled:opacity-50">คืนเครดิต</button></>}>
    <input autoFocus value={reason} onChange={e=>setReason(e.target.value)} placeholder="เหตุผลการปฏิเสธ…" className="mt-4 h-10 w-full rounded-lg border border-line bg-sunken px-3 text-sm text-fg"/>
    <div className="mt-2.5 text-xs leading-relaxed text-muted">เลือก <b className="text-accent">คืนเครดิต</b> เพื่อคืนยอดให้ลูกค้า หรือ <b className="text-danger">ตัดเครดิต</b> เพื่อไม่คืนยอดที่หักไปตอนยื่นถอน</div>
  </WdModalShell>);
}
/* แก้บัญชีที่ถอนจริง (ทำได้ 1 ครั้ง เฉพาะรายการที่จ่ายแล้ว) — ให้สรุปยอดตามบัญชีถูกต้อง */
function WithdrawCorrectModal({ row, onClose, onDone, toast }) {
  const [f,setF]=useState({bank_code:"KBANK",account_no:"",account_name:""}),[busy,setBusy]=useState(false);
  const submit=async()=>{ if(!f.account_no.trim()||!f.account_name.trim()) return toast("กรุณากรอกข้อมูลให้ครบ"); setBusy(true);
    try{ await api("/withdrawals/"+row.id+"/correct-account",{method:"PATCH",body:{bank_code:f.bank_code,account_no:f.account_no.trim(),account_name:f.account_name.trim()}});
      toast("แก้ไขบัญชีถอนแล้ว"); onDone&&onDone(); onClose(); }
    catch(e){ toast(e.message||"แก้ไขไม่สำเร็จ"); } finally{ setBusy(false); } };
  const inp="mt-1 h-10 w-full rounded-lg border border-line bg-sunken px-3 text-sm text-fg";
  return (<WdModalShell title="แก้ไขบัญชีถอน" sub={(row.username||"-")+" · "+money2(row.amount)} busy={busy} onClose={onClose}
    footer={<><button onClick={onClose} disabled={busy} className="h-9 rounded-lg border border-line bg-surface px-3 text-sm font-medium text-fg-2 hover:bg-sunken">ยกเลิก</button>
      <button onClick={submit} disabled={busy} className="h-9 rounded-lg bg-accent px-4 text-sm font-semibold text-accent-fg disabled:opacity-50">{busy?"กำลังบันทึก…":"บันทึก (1 ครั้ง)"}</button></>}>
    <div className="mt-3 rounded-lg border border-warn/40 bg-warn-soft px-3 py-2 text-xs text-fg-2">⚠️ แก้ไขได้ 1 ครั้ง เพื่อให้บัญชีสรุปยอดถูกต้อง</div>
    <label className="mt-3 block"><span className="text-xs font-medium text-fg-2">ธนาคารที่ถอนจริง</span>
      <select value={f.bank_code} onChange={e=>setF(x=>({...x,bank_code:e.target.value}))} className={inp}>{WD_CORRECT_BANKS.map(([c,n])=><option key={c} value={c}>{c} – {n}</option>)}</select></label>
    <label className="mt-3 block"><span className="text-xs font-medium text-fg-2">เลขบัญชีที่ถอนจริง</span>
      <input value={f.account_no} onChange={e=>setF(x=>({...x,account_no:e.target.value}))} placeholder="123-456-7890" className={inp+" mono"}/></label>
    <label className="mt-3 block"><span className="text-xs font-medium text-fg-2">ชื่อบัญชีที่ถอนจริง</span>
      <input value={f.account_name} onChange={e=>setF(x=>({...x,account_name:e.target.value}))} placeholder="ชื่อ-นามสกุล" className={inp}/></label>
  </WdModalShell>);
}
/* การ์ดยอดถอนต่อบัญชี (เมื่อวาน / วันนี้) — /withdrawal-accounts */
function WdrAccountCards({ accounts }) {
  const list=(accounts||[]).filter(a=>a.is_active);
  if(!list.length) return null;
  return (<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3">{list.map(a=>{ const tmn=a.type==="TMNWD"||a.type==="wallet";
    return (<div key={a.id} className="rounded-xl border border-line bg-surface p-3 shadow-sm">
      <div className="flex items-center gap-2"><BankLogo code={tmn?"truewallet":a.bank_code} size={26}/>
        <div className="min-w-0"><div className="truncate text-sm font-semibold">{tmn?(a.type==="TMNWD"?"TMN ถอน (TMNWD)":"บัญชีวอลเล็ท"):(a.bank_name||bankName(a.bank_code))}</div>
          <div className="truncate text-[11px] text-muted">{tmn?(a.wallet_phone||a.account_name||""):[a.account_no,a.account_name].filter(Boolean).join(" · ")}</div></div></div>
      <div className="mt-2.5 grid grid-cols-2 gap-2 text-xs">
        <div className="rounded-lg bg-sunken/70 px-2.5 py-1.5"><div className="text-muted">เมื่อวาน</div><div className="font-semibold tnum">{money2(a.withdraw_total_yesterday)}</div><div className="text-[11px] text-muted tnum">{N(a.withdraw_count_yesterday)} ครั้ง</div></div>
        <div className="rounded-lg bg-danger-soft px-2.5 py-1.5"><div className="text-muted">วันนี้</div><div className="font-semibold tnum text-danger">-{money2(a.withdraw_total_today)}</div><div className="text-[11px] text-muted tnum">{N(a.withdraw_count_today)} ครั้ง</div></div>
      </div>
    </div>); })}</div>);
}
/* ---------- ถอนไม่ครบ (Autopeer): peer โอนให้ลูกค้าไม่ครบแล้วตีกลับมาให้แอดมินโอนส่วนที่เหลือเอง ---------- */
const AP_WD_STATUS = { PENDING:["กำลังโอน","info"], SUCCESS:["สำเร็จ","success"], TIMEOUT:["หมดเวลา","danger"], EXPIRED:["หมดเวลา","danger"], CANCEL:["ยกเลิก","danger"], CANCELLED:["ยกเลิก","danger"], REJECT:["ปฏิเสธ","danger"], REJECTED:["ปฏิเสธ","danger"] };
const apWdStatus = (s)=>AP_WD_STATUS[String(s||"").toUpperCase()] || [s||"-","warn"];
function AutopeerShortfallView({ toast }) {
  const [data,setData]=useState(null),[loading,setLoading]=useState(true),[err,setErr]=useState(null),[wdModal,setWdModal]=useState(null),[showActive,setShowActive]=useState(false);
  const load=useCallback(async()=>{ setLoading(true); setErr(null);
    try{ setData(await api("/autopeer/withdraw-shortfalls")); }
    catch(e){ if(e.status===401)window.__nxAuthFail&&window.__nxAuthFail(); setErr(e.status===403?"บัญชีนี้ไม่มีสิทธิ์ดูหน้านี้":(e.message||"โหลดไม่สำเร็จ")); }
    finally{ setLoading(false); } },[]);
  useEffect(()=>{ load(); },[load]);
  const canAct=can("wdr");
  const all=(data&&data.rows)||[];
  const isActive=(r)=>String(r.ap&&r.ap.status||"").toUpperCase()==="PENDING";
  const rows=showActive?all:all.filter(r=>!isActive(r));
  const activeCount=all.length-all.filter(r=>!isActive(r)).length;
  const sumRemaining=rows.reduce((s,r)=>s+N(r.ap.remaining),0);
  const sumPaid=rows.reduce((s,r)=>s+N(r.ap.paid),0);
  const copy=(t)=>{ try{ navigator.clipboard.writeText(String(t)); toast("คัดลอกแล้ว: "+t); }catch{ toast("คัดลอกไม่สำเร็จ"); } };
  const H=({children,extra=""})=>(<th className={"whitespace-nowrap px-3 py-2.5 text-left text-[13px] font-bold text-fg-2 "+extra}>{children}</th>);
  return (<div className="space-y-3">
    <div className="flex flex-wrap items-center gap-2">
      <div className="text-xs text-muted">รายการถอน Autopeer ที่ยังรอถอน และ Autopeer โอนให้ลูกค้าไม่ครบยอด (ย้อนหลัง {data?data.days:14} วัน) — โอน <b className="text-fg-2">เฉพาะส่วนที่เหลือ</b> แล้วกดอนุมัติ</div>
      <label className="ml-auto flex items-center gap-1.5 text-xs text-fg-2"><input type="checkbox" checked={showActive} onChange={e=>setShowActive(e.target.checked)}/> แสดงรายการที่ Autopeer ยังโอนอยู่{activeCount?" ("+activeCount+")":""}</label>
      <button onClick={load} className="flex h-9 items-center gap-1.5 rounded-lg border border-line bg-surface px-3 text-sm font-medium text-fg-2 hover:bg-sunken"><Ic d={I.refresh} size={16} cls={loading?"animate-spin":""}/> รีเฟรช</button>
    </div>
    {!loading&&!err&&<div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
      <StatMini k="รายการที่โอนไม่ครบ" v={rows.length.toLocaleString("th-TH")} color="var(--warn)"/>
      <StatMini k="Autopeer โอนแล้ว" v={bahtNum(sumPaid)+" บาท"} color="var(--success)"/>
      <StatMini k="ต้องโอนเพิ่ม (ถอนมือ)" v={bahtNum(sumRemaining)+" บาท"} color="var(--danger)"/>
    </div>}
    {err ? <HistErr msg={err} onRetry={load}/>
    : (<div className="overflow-hidden rounded-xl border border-line bg-surface shadow-sm"><div className="overflow-x-auto"><table className="w-full min-w-[1000px] border-collapse text-sm">
      <thead className="border-b-2 border-accent/25 bg-accent-soft"><tr>
        <H>เวลา</H><H>สมาชิก</H><H>บัญชีรับ (ลูกค้า)</H><H extra="text-right">ยอดถอน</H><H extra="text-right">Autopeer โอนแล้ว</H><H extra="text-right">ต้องโอนเพิ่ม</H><H>สถานะ Autopeer</H><H extra="text-right pr-4">จัดการ</H>
      </tr></thead>
      <tbody>
        {loading ? Array.from({length:4}).map((_,i)=>(<tr key={i} className="border-b border-line-soft"><td className="px-3 py-3" colSpan="8"><div className="skel h-5 w-full"/></td></tr>))
        : rows.length===0 ? (<tr><td colSpan="8" className="px-4 py-16 text-center text-sm font-medium text-fg-2">ไม่มีรายการที่โอนไม่ครบ</td></tr>)
        : rows.map(r=>{ const nm=r.username||r.full_name||"-"; const wd=withdrawDest(r); const st=apWdStatus(r.ap.status);
          return (<tr key={r.id} className="border-b border-line-soft last:border-0 hover:bg-sunken/50">
            <td className="whitespace-nowrap px-3 py-2.5 text-xs text-fg-2">{fmtDT(r.created_at)}<div className="mono text-[10px] text-faint">{r.ap_ref}</div></td>
            <td className="px-3"><div className="truncate font-semibold text-accent">{nm}</div><div className="truncate text-[11px] text-muted">{r.full_name&&r.full_name!==r.username?r.full_name+" · ":""}{r.phone||"-"}</div></td>
            <td className="px-3"><div className="flex items-center gap-1.5"><BankLogo code={wd.code} size={22}/><div className="min-w-0"><button title="คัดลอกเลขบัญชี" onClick={()=>wd.no&&copy(wd.no)} className="truncate mono text-xs text-fg-2 hover:text-accent">{[bankName(wd.code),wd.no].filter(Boolean).join(" ")||"-"}</button>{wd.name&&<div className="truncate text-[11px] text-faint">{wd.name}</div>}</div></div></td>
            <td className="whitespace-nowrap px-3 text-right tnum text-fg-2">{money2(r.amount)}</td>
            <td className="whitespace-nowrap px-3 text-right tnum text-success">{bahtNum(r.ap.paid)} บาท</td>
            <td className="whitespace-nowrap px-3 text-right"><button title="คัดลอกยอด" onClick={()=>copy(r.ap.remaining)} className="font-bold tnum text-danger hover:underline">{bahtNum(r.ap.remaining)} บาท</button></td>
            <td className="px-3"><Badge tone={st[1]}>{st[0]}</Badge></td>
            <td className="pr-4"><div className="flex justify-end">{canAct&&<button onClick={()=>setWdModal(r)} className="h-7 rounded-lg px-3 text-xs font-semibold text-white" style={{background:"var(--success)"}}>โอนแล้ว · อนุมัติ</button>}</div></td>
          </tr>); })}
      </tbody>
    </table></div></div>)}
    {wdModal&&<WithdrawApproveModal row={wdModal} onClose={()=>setWdModal(null)} onDone={load} toast={toast}
      notice={<div className="mt-3 rounded-lg border border-warn/40 bg-warn-soft px-3 py-2 text-xs text-fg-2">⚠️ Autopeer โอนให้ลูกค้าแล้ว <b className="tnum">{bahtNum(wdModal.ap.paid)}</b> บาท — โอนเพิ่มเฉพาะ <b className="tnum text-danger">{bahtNum(wdModal.ap.remaining)} บาท</b> ก่อนกดอนุมัติ ห้ามโอนเต็มยอด</div>}/>}
  </div>);
}
function FinancePage({ kind, toast }) {
  const isDep = kind==="deposit";
  const EP = isDep ? "/deposits" : "/withdrawals";
  const STATUS = isDep
    ? [["","ทั้งหมด"],["success","สำเร็จ"],["pending","รอ"],["rejected","ปฏิเสธ"]]
    : [["pending","รอถอน"],["paid","จ่ายแล้ว"],["rejected","ปฏิเสธ"]]; // API ไม่มี "ทั้งหมด" ไม่ส่ง status = pending
  const [status,setStatus]=useState(isDep?"":"pending");
  const [q,setQ]=useState("");
  const [range,setRange]=useState(isDep?"":"today");
  const [wf,setWf]=useState({account:"",amount:""}); // ตัวกรองเฉพาะถอน: เลขบัญชี / ยอด (บาท)
  const [wdAccts,setWdAccts]=useState([]);
  const [custom,setCustom]=useState({from:bkkDate(6),to:bkkDate(0)});
  const [rows,setRows]=useState([]);
  const [loading,setLoading]=useState(true);
  const [err,setErr]=useState(null);
  const [detail,setDetail]=useState(null);
  const [modal,setModal]=useState(null);
  const [histUid,setHistUid]=useState(null); // กดยูสในลิสต์ → เปิดประวัติลูกค้า (ลดขั้นตอนไม่ต้องไปค้นหน้าสมาชิก)
  const [payoutRow,setPayoutRow]=useState(null);
  const [busy,setBusy]=useState(false);
  const [view,setView]=useState("list");
  const debRef=useRef(null);
  const load=useCallback(async(st,query,rg,cust,extra)=>{
    setLoading(true);setErr(null);
    try {
      const p=new URLSearchParams(); p.set("limit","200");
      if(st) p.set("status",st);
      if(query) p.set("q",query);
      if(rg){ const {from,to}=rangeToDates(rg,cust); p.set("from",from); p.set("to",to); }
      if(extra&&extra.account) p.set("account",extra.account);
      if(extra&&extra.amount) p.set("amount",extra.amount);
      if(!isDep) api("/withdrawal-accounts").then(a=>setWdAccts(Array.isArray(a)?a:[])).catch(()=>{});
      const data=await api(EP+"?"+p.toString());
      setRows(Array.isArray(data)?data:(data.rows||[]));
    } catch(e){ if(e.status===401)window.__nxAuthFail&&window.__nxAuthFail(); setErr(e.status===403?"บัญชีนี้ไม่มีสิทธิ์ดูหน้านี้":(e.message||"โหลดไม่สำเร็จ")); }
    finally{setLoading(false);}
  },[EP,isDep]);
  const wfq={account:wf.account.trim(),amount:wf.amount.trim()};
  useEffect(()=>{ load(status,q.trim(),range,custom,wfq); },[status,range,load]);
  const typedOnce=useRef(false); // ข้ามรอบแรกตอนเปิดหน้า ไม่งั้นโหลดซ้ำกับ effect ด้านบน
  useEffect(()=>{ if(!typedOnce.current){ typedOnce.current=true; return; } if(debRef.current)clearTimeout(debRef.current); debRef.current=setTimeout(()=>load(status,q.trim(),range,custom,wfq),350); return ()=>clearTimeout(debRef.current); },[q,wf.account,wf.amount]);
  const reload=()=>load(status,q.trim(),range,custom,wfq);
  const [wdModal,setWdModal]=useState(null); // {type:"approve"|"reject"|"correct", row}
  const toggleStar=async(r)=>{ try{ await api("/withdrawals/"+r.id+"/star",{method:"PATCH",body:{star:!r.star}}); reload(); }catch(e){ toast(e.message||"ไม่สำเร็จ"); } };
  const toggleHide=async(r)=>{ try{ await api("/withdrawals/"+r.id+"/hide",{method:"PATCH",body:{hide:!r.hidden_from_user}}); toast(r.hidden_from_user?"แสดงรายการถอนแล้ว":"ซ่อนรายการถอนแล้ว"); reload(); }catch(e){ toast(e.message||"ไม่สำเร็จ"); } };
  const [page,setPage]=useState(1); const [size,setSize]=useState(50);
  useEffect(()=>{ setPage(1); },[status,range,q,wf.account,wf.amount,rows.length]);
  const paged=rows.slice((page-1)*size, page*size);
  // โอนแล้ว / ต้องโอน ของรายการถอน Autopeer ในหน้าที่แสดงอยู่ (ดึงจาก Autopeer ทีละไม่เกิน 20 ref)
  const [apProg,setApProg]=useState({});
  const apRefs = isDep ? [] : [...new Set(paged.map(withdrawAutopeerRef).filter(Boolean))].slice(0,20);
  const apKey = apRefs.join(",");
  useEffect(()=>{
    if(!apKey){ setApProg({}); return; }
    let alive=true;
    api("/autopeer/withdraw-progress",{method:"POST",body:{refs:apRefs}}).then(m=>{ if(alive) setApProg(m||{}); }).catch(()=>{});
    return ()=>{ alive=false; };
  },[apKey]);
  // ----- สรุปยอด / รวมยอด / แยกตามบัญชี (คิดจากรายการที่โหลดตามตัวกรองปัจจุบัน) -----
  const amtOf=(r)=>Number((isDep?(r.gross_amount!=null?r.gross_amount:r.amount):r.amount)||0);
  const isDone=(r)=>{ const st=String(r.status||"").toLowerCase(); return isDep?st==="success":st==="paid"; };
  const sumTotal=rows.reduce((s,r)=>s+amtOf(r),0);
  const sumDone=rows.reduce((s,r)=>s+(isDone(r)?amtOf(r):0),0);
  const cntDone=rows.reduce((s,r)=>s+(isDone(r)?1:0),0);
  const acctMap={};
  rows.forEach(r=>{
    const key=isDep
      ? [bankName(r.bank_code),r.account_no||r.wallet_phone,r.account_name].filter(Boolean).join(" · ")
      : [r.pa_bank_name||bankName(r.pa_bank_code),r.pa_account_no,r.pa_account_name].filter(Boolean).join(" · ");
    const k=key||"ไม่ระบุบัญชี";
    if(!acctMap[k])acctMap[k]={count:0,amt:0,done:0};
    acctMap[k].count++; acctMap[k].amt+=amtOf(r); if(isDone(r))acctMap[k].done+=amtOf(r);
  });
  const acctRows=Object.entries(acctMap).map(([k,v])=>({k,...v})).sort((a,b)=>b.amt-a.amt);
  const doExportFin=()=>{ const H=isDep?["เวลา","ยูส","ชื่อสมาชิก","เบอร์","ช่องทาง","ยอด(บาท)","บัญชีลูกค้า","สถานะ"]:["เวลา","ยูส","ชื่อสมาชิก","เบอร์","ประเภท","ก่อนถอน(บาท)","ยอด(บาท)","คงเหลือ(บาท)","บัญชีรับ","บัญชีจ่าย","ผู้ทำ","สถานะ"];
    const body=rows.map(r=>{ const amt=(Number((isDep?(r.gross_amount!=null?r.gross_amount:r.amount):r.amount)||0)/100).toFixed(2);
      return isDep?[fmtDT(r.created_at),r.username,r.full_name,r.phone,(CHANNEL_LABEL[r.channel]||r.channel),amt,[bankName(r.user_bank_code),r.user_bank_account_no].filter(Boolean).join(" "),depStatus(r.status).t]
                  :[fmtDT(r.created_at),r.username,r.full_name,r.phone,withdrawTypeLabel(r),r.credit_before!=null?(N(r.credit_before)/100).toFixed(2):"",amt,r.credit_after!=null?(N(r.credit_after)/100).toFixed(2):"",(d=>[bankName(d.code),d.no].filter(Boolean).join(" "))(withdrawDest(r)),[r.pa_bank_name||bankName(r.pa_bank_code),r.pa_account_no].filter(Boolean).join(" "),(r.processed_by_fullname||r.processed_by_username),depStatus(r.status).t]; });
    csvDownload((isDep?"deposits-":"withdrawals-")+bkkDate(0)+".csv",[H,...body]); toast("ส่งออก "+rows.length+" รายการแล้ว"); };
  const doApprove=async(username)=>{ if(!modal||!modal.row)return; setBusy(true);
    try{ const body = isDep ? ((username && username.toLowerCase()!==String(modal.row.username||"").toLowerCase())?{username}:{}) : {};
      await api(EP+"/"+modal.row.id+"/approve",{method:"POST",body}); toast(isDep?"อนุมัติรายการฝากแล้ว":"อนุมัติการถอนแล้ว"); setModal(null); reload();
    }catch(e){toast(e.message||"ไม่สำเร็จ");}finally{setBusy(false);} };
  const doReject=async(reason)=>{ if(!modal||!modal.row)return; setBusy(true);
    try{ await api(EP+"/"+modal.row.id+"/reject",{method:"POST",body:{reason:reason||"rejected",note:reason||"rejected"}}); toast("ปฏิเสธแล้ว"); setModal(null); reload();
    }catch(e){toast(e.message||"ไม่สำเร็จ");}finally{setBusy(false);} };
  const H=({children,extra=""})=>(<th className={"whitespace-nowrap px-3 py-2.5 text-left text-[13px] font-bold text-fg-2 "+extra}>{children}</th>);
  const isPending=(r)=>String(r.status||"").toLowerCase()==="pending";
  const canAct = isDep ? canAny(["deposits","tool_slip_approve"]) : can("wdr");
  const openDetail=(r)=>{
    const nm=r.username||r.full_name||"-";
    const rowsKV = isDep ? [
      ["เวลา",fmtDT(r.created_at)],["สมาชิก",nm+(r.full_name&&r.full_name!==r.username?" ("+r.full_name+")":"")],["เบอร์",r.phone],
      ["ช่องทาง",CHANNEL_LABEL[r.channel]||r.channel],["ยอด",money2(r.gross_amount!=null?r.gross_amount:r.amount)],
      ["บัญชีรับ",[bankName(r.bank_code),r.account_no||r.wallet_phone,r.account_name].filter(Boolean).join(" · ")],
      ["บัญชีลูกค้า",[bankName(r.user_bank_code),r.user_bank_account_no,r.user_bank_account_name].filter(Boolean).join(" · ")],
      ["Ref",r.ref_id],["เครดิตก่อน→หลัง",r.credit_before!=null?(money2(r.credit_before)+" → "+money2(r.credit_after)):null],
      ["ผู้ทำ",r.operator_name||(r.meta&&r.meta.adminUsername)],["หมายเหตุ",r.note&&r.note!=="-"?r.note:null],
    ] : [
      ["เวลา",fmtDT(r.created_at)],["สมาชิก",nm+(r.full_name&&r.full_name!==r.username?" ("+r.full_name+")":"")],["เบอร์",r.phone],
      ["ยอด",money2(r.amount)],["ประเภท",withdrawTypeLabel(r)],["สถานะ",depStatus(r.status).t],
      ["บัญชีรับ (ลูกค้า)",(d=>[d.code?bankName(d.code):"",d.no,d.name].filter(Boolean).join(" · ")+(d.fixed?" (แก้บัญชีแล้ว)":""))(withdrawDest(r))],
      ["บัญชีจ่าย (ของเรา)",[r.pa_bank_name||bankName(r.pa_bank_code),r.pa_account_no,r.pa_account_name].filter(Boolean).join(" · ")],
      ["เครดิตก่อน→หลัง",r.credit_before!=null?(money2(r.credit_before)+" → "+money2(r.credit_after)):null],
      ["ผู้ทำ",r.processed_by_fullname||r.processed_by_username],["เวลาที่ทำ",r.processed_at?fmtDT(r.processed_at):null],
      ["Autopeer Ref",r.autopeer_ref||r.provider_ref||parseWithdrawMeta(r).autopeerRef||null],
      ["Autopeer โอนแล้ว / ต้องโอน",autopeerProgressText(apProg[withdrawAutopeerRef(r)])||null],
      ["หมายเหตุ",withdrawNote(r)],["REF",r.id],
    ];
    setDetail({ title:money2(isDep?(r.gross_amount!=null?r.gross_amount:r.amount):r.amount), subtitle:nm+" · "+(r.username||""), tone:depStatus(r.status), rows:rowsKV, slip:isDep?slipUrl(r):"" });
  };
  return (<div className="space-y-3">
    <div className="flex items-center gap-1 rounded-lg border border-line bg-sunken p-1 w-fit">
      <button onClick={()=>setView("list")} className={"rounded-md px-3 py-1.5 text-xs font-semibold transition-colors "+(view==="list"?"bg-accent text-accent-fg shadow-sm":"text-fg-2 hover:text-fg")}>รายการ{isDep?"ฝาก":"ถอน"}</button>
      <button onClick={()=>setView("summary")} className={"rounded-md px-3 py-1.5 text-xs font-semibold transition-colors "+(view==="summary"?"bg-accent text-accent-fg shadow-sm":"text-fg-2 hover:text-fg")}>สรุปยอด</button>
    </div>
    <div className="flex flex-wrap items-center gap-2">
      {view!=="shortfall" && <div className="relative flex-1 sm:max-w-xs">
        <span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted"><Ic d={I.search} size={16}/></span>
        <input value={q} onChange={(e)=>setQ(e.target.value)} placeholder="ค้นหา ชื่อ / ยูส / เบอร์…" className="h-9 w-full rounded-lg border border-line bg-surface pl-9 pr-3 text-sm text-fg placeholder:text-faint focus:border-accent focus:outline-none focus:ring-4 focus:ring-[var(--accent-ring)]"/>
      </div>}
      <div className="flex flex-wrap items-center gap-1 rounded-lg border border-line bg-sunken p-0.5">
        {STATUS.map(([k,l])=>(<button key={k||"all"} onClick={()=>{ setStatus(k); if(view==="shortfall") setView("list"); }} className={"rounded-md px-2.5 py-1 text-xs font-medium transition-colors "+(view!=="shortfall"&&status===k?"bg-accent text-accent-fg shadow-sm":"text-fg-2 hover:text-fg")}>{l}</button>))}
      </div>
      {!isDep&&<button onClick={()=>setView("shortfall")} className={"h-[30px] rounded-lg border px-3 text-xs font-semibold transition-colors "+(view==="shortfall"?"border-accent bg-accent text-accent-fg shadow-sm":"border-line bg-sunken text-fg-2 hover:text-fg")}>P2P ถอนไม่ครบ</button>}
      {view!=="shortfall" && <>
      <div className="flex flex-wrap items-center gap-1 rounded-lg border border-line bg-sunken p-0.5">
        {FIN_RANGES.map(([k,l])=>(<button key={k||"none"} onClick={()=>setRange(k)} className={"rounded-md px-2 py-1 text-xs font-medium transition-colors "+(range===k?"bg-accent text-accent-fg shadow-sm":"text-fg-2 hover:text-fg")}>{l}</button>))}
      </div>
      {range==="custom" && (<div className="flex items-center gap-1.5">
        <input type="date" value={custom.from} onChange={(e)=>setCustom(c=>({...c,from:e.target.value}))} className="h-8 rounded-lg border border-line bg-surface px-2 text-xs"/>
        <span className="text-xs text-faint">-</span>
        <input type="date" value={custom.to} onChange={(e)=>setCustom(c=>({...c,to:e.target.value}))} className="h-8 rounded-lg border border-line bg-surface px-2 text-xs"/>
        <button onClick={()=>load(status,q.trim(),"custom",custom,wfq)} className="h-8 rounded-lg bg-accent px-3 text-xs font-semibold text-accent-fg">ดู</button>
      </div>)}
      {!isDep&&<>
        <input value={wf.account} onChange={e=>setWf(f=>({...f,account:e.target.value}))} placeholder="เลขบัญชี" className="h-9 w-32 rounded-lg border border-line bg-surface px-3 text-sm mono placeholder:font-sans placeholder:text-faint"/>
        <input value={wf.amount} onChange={e=>setWf(f=>({...f,amount:e.target.value}))} type="number" min="0" step="1" placeholder="ยอดถอน (บาท)" className="h-9 w-32 rounded-lg border border-line bg-surface px-3 text-sm placeholder:text-faint"/>
      </>}
      <button onClick={reload} className="flex h-9 items-center gap-1.5 rounded-lg border border-line bg-surface px-3 text-sm font-medium text-fg-2 hover:bg-sunken"><Ic d={I.refresh} size={16} cls={loading?"animate-spin":""}/> รีเฟรช</button>
      <ExportBtn onClick={doExportFin}/>
      <div className="ml-auto hidden text-xs text-muted sm:block tnum">{rows.length} รายการ</div>
      </>}
    </div>
    {view==="shortfall" && <AutopeerShortfallView toast={toast}/>}

    {view==="summary" && !loading && !err && (<>
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
        <StatMini k="จำนวนรายการ" v={rows.length.toLocaleString("th-TH")} color="var(--info)"/>
        <StatMini k={isDep?"ยอดฝากรวม":"ยอดถอนรวม"} v={money2(sumTotal)} color={isDep?"var(--success)":"var(--warn)"}/>
        <StatMini k={isDep?"ฝากสำเร็จ":"จ่ายแล้ว"} v={money2(sumDone)} sub={cntDone.toLocaleString("th-TH")+" รายการ"} color="var(--success)"/>
        <StatMini k="บัญชีที่เกี่ยวข้อง" v={acctRows.length.toLocaleString("th-TH")} color="var(--accent)"/>
      </div>
      <div className="overflow-hidden rounded-xl border border-line bg-surface shadow-sm">
        <div className="border-b border-line px-4 py-2.5 text-[13px] font-bold text-fg-2">{isDep?"แยกตามบัญชีรับเงิน (ฝาก)":"แยกตามบัญชีจ่ายเงิน (ถอน)"}</div>
        <div className="overflow-x-auto"><table className="w-full min-w-[520px] border-collapse text-sm">
          <thead className="border-b-2 border-accent/25 bg-accent-soft"><tr>
            <th className="whitespace-nowrap px-3 py-2.5 text-left text-[13px] font-bold text-fg-2">บัญชี / ชื่อบัญชี</th>
            <th className="whitespace-nowrap px-3 py-2.5 text-right text-[13px] font-bold text-fg-2">จำนวน</th>
            <th className="whitespace-nowrap px-3 py-2.5 text-right text-[13px] font-bold text-fg-2">ยอดรวม</th>
            <th className="whitespace-nowrap px-3 py-2.5 text-right text-[13px] font-bold text-fg-2 pr-4">{isDep?"สำเร็จ":"จ่ายแล้ว"}</th>
          </tr></thead>
          <tbody>
            {acctRows.map((a,i)=>(<tr key={a.k||i} className="border-b border-line-soft last:border-0 hover:bg-sunken/50">
              <td className="px-3 py-2 font-medium text-fg">{a.k}</td>
              <td className="px-3 text-right tnum text-fg-2">{a.count.toLocaleString("th-TH")}</td>
              <td className={"px-3 text-right tnum font-semibold "+(isDep?"text-success":"text-warn")}>{money2(a.amt)}</td>
              <td className="px-3 pr-4 text-right tnum text-success">{money2(a.done)}</td>
            </tr>))}
            <tr className="bg-sunken/70 font-bold">
              <td className="px-3 py-2.5">รวมทั้งหมด</td>
              <td className="px-3 text-right tnum">{rows.length.toLocaleString("th-TH")}</td>
              <td className="px-3 text-right tnum">{money2(sumTotal)}</td>
              <td className="px-3 pr-4 text-right tnum text-success">{money2(sumDone)}</td>
            </tr>
          </tbody>
        </table></div>
      </div>
    </>)}
    {view==="summary" && loading && (
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">{Array.from({length:4}).map((_,i)=><div key={i} className="rounded-xl border border-line bg-surface p-4"><div className="skel h-3 w-24"/><div className="skel mt-3 h-7 w-32"/></div>)}</div>
    )}
    {view==="summary" && !loading && err && (
      <div className="rounded-xl border border-line bg-surface px-4 py-14 text-center shadow-sm">
        <div className="text-sm font-semibold text-danger">{err}</div>
        <button onClick={reload} className="mt-3 rounded-lg border border-line px-3 py-1.5 text-xs font-medium text-fg-2 hover:bg-sunken">ลองโหลดสรุปยอดอีกครั้ง</button>
      </div>
    )}
    {view==="summary" && !loading && !err && rows.length===0 && (
      <div className="rounded-xl border border-line bg-surface px-4 py-14 text-center shadow-sm">
        <div className="mx-auto mb-2 grid h-10 w-10 place-items-center rounded-full text-muted" style={{background:"var(--sunken)"}}><Ic d={I.search} size={20}/></div>
        <div className="text-sm font-semibold text-fg-2">ไม่พบรายการสำหรับสรุปยอด</div>
        <div className="mt-1 text-xs text-muted">ลองเปลี่ยนสถานะ ช่วงเวลา หรือคำค้นหา แล้วกดรีเฟรช</div>
      </div>
    )}

    {view==="list" && !isDep && <WdrAccountCards accounts={wdAccts}/>}
    {view==="list" && (err ? (<div className="rounded-xl border border-line bg-surface px-4 py-16 text-center shadow-sm"><div className="mx-auto mb-2 grid h-10 w-10 place-items-center rounded-full text-danger" style={{background:"var(--danger-soft)"}}><Ic d={I.warn2} size={20}/></div><div className="text-sm font-medium text-fg-2">{err}</div><button onClick={reload} className="mt-3 rounded-lg border border-line px-3 py-1.5 text-xs font-medium text-fg-2 hover:bg-sunken">ลองใหม่</button></div>)
    : (<div className="overflow-hidden rounded-xl border border-line bg-surface shadow-sm"><div className="overflow-x-auto"><table className={"w-full border-collapse text-sm "+(isDep?"min-w-[900px]":"min-w-[1180px]")}>
      <thead className="border-b-2 border-accent/25 bg-accent-soft"><tr>
        <H>เวลา</H><H>สมาชิก</H>{isDep?<H>ช่องทาง</H>:<H>ประเภท</H>}<H>{isDep?"บัญชีลูกค้า":"บัญชีรับ (ลูกค้า)"}</H>{!isDep&&<H>บัญชีจ่าย (ของเรา)</H>}{!isDep&&<H extra="text-right">ก่อนถอน</H>}<H extra="text-right">ยอด</H>{!isDep&&<H extra="text-right">คงเหลือ</H>}{!isDep?<H>ผู้ทำ</H>:null}<H>สถานะ</H><H extra="text-right pr-4 sticky right-0 z-10 bg-accent-soft shadow-[-8px_0_8px_-8px_rgba(0,0,0,.18)]">จัดการ</H>
      </tr></thead>
      <tbody>
        {loading ? Array.from({length:8}).map((_,i)=>(<tr key={i} className="border-b border-line-soft"><td className="px-3 py-3" colSpan={isDep?7:11}><div className="skel h-5 w-full"/></td></tr>))
          : rows.length===0 ? (<tr><td colSpan={isDep?8:11} className="px-4 py-16 text-center"><div className="text-sm font-medium text-fg-2">ไม่มีรายการ</div></td></tr>)
          : paged.map((r,idx)=>{ const nm=r.username||r.full_name||"-"; const st=depStatus(r.status); const slip=isDep?slipUrl(r):"";
            const wd = isDep ? null : withdrawDest(r);
            const custBank = isDep ? [bankName(r.user_bank_code),r.user_bank_account_no].filter(Boolean).join(" ") : [bankName(wd.code),wd.no].filter(Boolean).join(" ");
            const custName = isDep ? r.user_bank_account_name : wd.name;
            const stl = String(r.status||"").toLowerCase();
            const payoutName = r.payout_account_id ? payoutAccountLabel({type:r.pa_type,bank_name:r.pa_bank_name,bank_code:r.pa_bank_code,account_no:r.pa_account_no,account_name:r.pa_account_name,wallet_phone:r.pa_wallet_phone}) : "";
            return (<tr key={r.id||idx} className="border-b border-line-soft transition-colors last:border-0 hover:bg-sunken/50">
              <td className="whitespace-nowrap px-3 py-2.5 text-xs text-fg-2">{fmtDT(r.created_at)}</td>
              <td className="px-3"><div className="flex items-center gap-2.5">{!isDep&&canAct&&<button title={r.star?"เอาดาวออก":"ติดดาว"} onClick={()=>toggleStar(r)} className={"text-base leading-none "+(r.star?"text-warn":"text-faint hover:text-warn")}>{r.star?"★":"☆"}</button>}<div className="grid h-8 w-8 shrink-0 place-items-center rounded-full text-sm font-semibold text-white" style={{background:avc(nm)}}>{initials(nm)}</div><div className="min-w-0"><button type="button" onClick={()=>r.user_id&&setHistUid(r.user_id)} disabled={!r.user_id} title={r.user_id?"ดูประวัติลูกค้า":""} className="block max-w-full truncate text-left font-semibold text-accent transition-colors hover:underline disabled:cursor-default disabled:no-underline">{nm}</button><div className="truncate text-[11px] text-muted">{r.full_name&&r.full_name!==r.username?r.full_name+" · ":""}{r.phone||"-"}</div></div></div></td>
              {isDep?<td className="whitespace-nowrap px-3 text-xs text-fg-2">{CHANNEL_LABEL[r.channel]||r.channel||"-"}</td>:<td className="whitespace-nowrap px-3"><span className="rounded-md bg-sunken px-1.5 py-0.5 text-[11px] font-medium text-fg-2">{withdrawTypeLabel(r)}</span><AutopeerProgress p={apProg[withdrawAutopeerRef(r)]}/></td>}
              <td className="px-3"><div className="flex items-center gap-1.5"><BankLogo code={isDep?r.user_bank_code:wd.code} size={22}/><div className="min-w-0"><div className="truncate mono text-xs text-fg-2">{custBank||"-"}</div>{custName && <div className="truncate text-[11px] text-faint">{custName}</div>}{wd&&wd.fixed&&<div className="text-[10px] font-semibold text-success">แก้บัญชีแล้ว</div>}</div></div></td>
              {!isDep&&<td className="px-3 text-xs">{payoutName?<span className="text-fg-2">{payoutName}</span>:<span className="text-danger">ยังไม่ระบุ</span>}</td>}
              {!isDep&&<td className="whitespace-nowrap px-3 text-right text-xs tnum text-muted">{r.credit_before!=null?money2(r.credit_before):"-"}</td>}
              <td className={"whitespace-nowrap px-3 text-right font-semibold tnum"+(isDep?"":" text-danger")}>{isDep?"":"-"}{money2(isDep?(r.gross_amount!=null?r.gross_amount:r.amount):r.amount)}</td>
              {!isDep&&<td className="whitespace-nowrap px-3 text-right text-xs font-semibold tnum text-info">{r.credit_after!=null?money2(r.credit_after):"-"}</td>}
              {!isDep?<td className="whitespace-nowrap px-3 text-xs text-fg-2">{r.processed_by_fullname||r.processed_by_username||"-"}</td>:null}
              <td className="px-3"><Badge tone={st.c}>{st.t}</Badge></td>
              {/* ปักคอลัมน์จัดการไว้ขวาสุด จอแคบแล้วปุ่มอนุมัติ/ปฏิเสธต้องไม่หลุดขอบ */}
              <td className="sticky right-0 z-10 bg-surface pl-3 pr-4 shadow-[-8px_0_8px_-8px_rgba(0,0,0,.18)]"><div className="flex items-center justify-end gap-1">
                {slip && <button title="ดูสลิป" onClick={()=>setModal({type:"slip",img:slip})} className="grid h-7 w-7 place-items-center rounded-lg border border-line bg-surface hover:bg-sunken" style={{color:"#0EA5E9"}}><Ic d={I.eye} size={14}/></button>}
                <button title="รายละเอียด" onClick={()=>openDetail(r)} className="grid h-7 w-7 place-items-center rounded-lg border border-line bg-surface hover:bg-sunken" style={{color:"#8B5CF6"}}><Ic d={I.copy} size={14}/></button>
                {!isDep&&canAct&&(isPending(r)||["paid","approved","success"].includes(stl))&&<button title={isPending(r)?"ระบุบัญชีถอน":"ปรับบัญชีจ่ายย้อนหลัง"} onClick={()=>setPayoutRow(r)} className="grid h-7 w-7 place-items-center rounded-lg border border-line bg-surface text-accent hover:bg-sunken"><Ic d={I.edit} size={14}/></button>}
                {!isDep&&canAct&&["paid","approved"].includes(stl)&&!r.corrected_account_no&&<button title="แก้บัญชีที่ถอนจริง (1 ครั้ง)" onClick={()=>setWdModal({type:"correct",row:r})} className="h-7 rounded-lg border border-line bg-surface px-2 text-[11px] font-medium text-fg-2 hover:bg-sunken">แก้บัญชี</button>}
                {!isDep&&canAct&&["rejected","failed"].includes(stl)&&<button title={r.hidden_from_user?"แสดงให้ลูกค้าเห็น":"ซ่อนจากลูกค้า"} onClick={()=>toggleHide(r)} className={"h-7 rounded-lg border px-2 text-[11px] font-medium hover:bg-sunken "+(r.hidden_from_user?"border-accent text-accent":"border-line text-fg-2")}>{r.hidden_from_user?"แสดง":"ซ่อน"}</button>}
                {isPending(r) && canAct && <><button title="ปฏิเสธ" onClick={()=>isDep?setModal({type:"reject",row:r}):setWdModal({type:"reject",row:r})} className="grid h-7 w-7 place-items-center rounded-lg border hover:bg-sunken" style={{borderColor:"var(--danger)",color:"var(--danger)"}}><Ic d={I.x} size={14}/></button>
                <button title={isDep?"เติมเงิน":"อนุมัติ"} onClick={()=>isDep?setModal({type:"approve",row:r}):setWdModal({type:"approve",row:r})} className="grid h-7 w-7 place-items-center rounded-lg text-white" style={{background:"var(--success)"}}><Ic d={I.check} size={14} sw={3}/></button></>}
              </div></td>
            </tr>);})}
      </tbody>
    </table></div>{!loading && <Pager page={page} setPage={setPage} total={rows.length} size={size} setSize={setSize}/>}</div>))}

    {view==="list" && detail && <DetailDrawer {...detail} onClose={()=>setDetail(null)}/>}
    {histUid && <UserHistoryPopup userId={histUid} onClose={()=>setHistUid(null)} toast={toast}/>}
    {view==="list" && wdModal && wdModal.type==="approve" && <WithdrawApproveModal row={wdModal.row} onClose={()=>setWdModal(null)} onDone={reload} toast={toast}/>}
    {view==="list" && wdModal && wdModal.type==="reject" && <WithdrawRejectModal row={wdModal.row} onClose={()=>setWdModal(null)} onDone={reload} toast={toast}/>}
    {view==="list" && wdModal && wdModal.type==="correct" && <WithdrawCorrectModal row={wdModal.row} onClose={()=>setWdModal(null)} onDone={reload} toast={toast}/>}
    {view==="list" && payoutRow && <WithdrawalAccountModal row={payoutRow} onClose={()=>setPayoutRow(null)} onDone={reload} toast={toast}/>}
    {view==="list" && modal && modal.type==="slip" && <SlipModal img={modal.img} onClose={()=>setModal(null)}/>}
    {view==="list" && modal && modal.type==="approve" && <ConfirmModal kind="approve" row={modal.row} busy={busy} hideInput={!isDep} titleText={isDep?undefined:"อนุมัติการถอน?"} descText={isDep?undefined:"ยืนยันจ่ายเงินให้ลูกค้ารายนี้"} onClose={()=>!busy&&setModal(null)} onConfirm={doApprove}/>}
    {view==="list" && modal && modal.type==="reject" && <ConfirmModal kind="reject" row={modal.row} busy={busy} titleText={isDep?undefined:"ปฏิเสธการถอน?"} onClose={()=>!busy&&setModal(null)} onConfirm={doReject}/>}
  </div>);
}
