/* Tachiara client — Room detail screen with all tabs + sub-panels. */

const splitLabel = (mode) => ({
  equal:   "Chia đều",
  select:  "Chia 1 nhóm",
  amount:  "Số tiền cụ thể",
  percent: "Theo %",
  shares:  "Theo phần",
}[mode] || mode);
window.splitLabel = splitLabel;

function RoomScreen({ me, navigate, roomId, onActivityChange }) {
  const [tab, setTab] = React.useState("overview");
  const [showAddExpense, setShowAddExpense] = React.useState(false);
  const [editingBill, setEditingBill] = React.useState(null);
  const [showInvite, setShowInvite] = React.useState(false);
  const [showSettings, setShowSettings] = React.useState(false);
  const [settleTransfer, setSettleTransfer] = React.useState(null);
  const toast = useToast();

  // Load everything for this room in parallel.
  const { data, loading, error, reload } = useApi(async () => {
    const [r, bills, settlements, bal] = await Promise.all([
      window.api.rooms.get(roomId),
      window.api.bills.list(roomId),
      window.api.settlements.list(roomId),
      window.api.rooms.balances(roomId),
    ]);
    return {
      room: r.room,
      members: bal.members,
      bills: bills.bills,
      settlements: settlements.settlements,
      balances: bal.balances,
      transfers: bal.transfers,
    };
  }, [roomId]);

  // Refetch when window regains focus (multi-tab use). KHÔNG auto-poll —
  // user phản hồi không thích nhấp nháy. Mutation tự gọi refreshAll() rồi.
  React.useEffect(() => {
    if (!roomId) return;
    const onFocus = () => reload();
    window.addEventListener("focus", onFocus);
    return () => window.removeEventListener("focus", onFocus);
  }, [roomId, reload]);

  // Helper: after any mutation, refresh both this room AND global notifications.
  const refreshAll = () => { reload(); onActivityChange && onActivityChange(); };

  if (loading) return <LoadingState />;
  if (error) return <ErrorState error={error} onRetry={reload} />;
  if (!data) return null;

  const { room, members, bills, settlements, balances, transfers } = data;
  const userById = (id) => members.find(u => u.id === id || u.id === String(id));
  const myBal = balances[me.id] || 0;
  const totalSpent = bills.reduce((s, b) => s + b.totalAmount, 0);

  // ── Mutations ──
  const performSettle = async (transfer) => {
    try {
      await window.api.settlements.create({
        roomId: room.id, fromUserId: transfer.fromUserId,
        toUserId: transfer.toUserId, amount: transfer.amount, note: "Đã thanh toán",
      });
      toast("Đã ghi nhận thanh toán");
      setSettleTransfer(null);
      refreshAll();
    } catch (err) { toast(err.message); }
  };

  const deleteBill = async (billId) => {
    if (!confirm("Xoá khoản chi này?")) return;
    try {
      await window.api.bills.delete(billId);
      toast("Đã xoá");
      refreshAll();
    } catch (err) { toast(err.message); }
  };

  const remind = async (transfer) => {
    try {
      await window.api.rooms.remind(room.id, transfer);
      const from = userById(transfer.fromUserId);
      toast(`Đã nhắc ${from?.name || "thành viên"}`);
      refreshAll();
    } catch (err) { toast(err.message); }
  };

  const undoSettlement = async (settlementId) => {
    if (!confirm("Huỷ thanh toán này? Số dư sẽ được tính lại như chưa thanh toán.")) return;
    try {
      await window.api.settlements.delete(settlementId);
      toast("Đã huỷ thanh toán");
      refreshAll();
    } catch (err) { toast(err.message); }
  };

  const confirmSettlement = async (settlementId) => {
    try {
      await window.api.settlements.confirm(settlementId);
      toast("Đã xác nhận nhận tiền");
      refreshAll();
    } catch (err) { toast(err.message); }
  };

  const rejectSettlement = async (settlementId) => {
    if (!confirm("Từ chối thanh toán này? (Ví dụ chưa thấy tiền vào tài khoản)")) return;
    try {
      await window.api.settlements.reject(settlementId);
      toast("Đã từ chối thanh toán");
      refreshAll();
    } catch (err) { toast(err.message); }
  };

  const exportCSV = async () => {
    try {
      await window.api.rooms.exportCsvUrl(room.id);
      toast("Đã tải CSV");
    } catch (err) { toast(err.message); }
  };

  return (
    <div>
      <div className="row-h" style={{ marginBottom: 16, gap: 6 }}>
        <button className="btn btn-ghost btn-sm" onClick={() => navigate({ screen: "rooms" })}>
          <span className="icon icon-sm"><I.arrowLeft /></span> Phòng
        </button>
      </div>

      <div className="page-header" style={{ alignItems: "flex-start" }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div className="row-h" style={{ gap: 10, marginBottom: 6 }}>
            <h1 className="page-title">{room.name}</h1>
            <CopyCode code={room.code} />
          </div>
          {room.description && <div className="page-subtitle">{room.description}</div>}
        </div>
        <div className="row-h" style={{ gap: 8 }}>
          <button className="btn btn-ghost btn-icon" onClick={() => setShowSettings(true)} title="Cài đặt phòng" aria-label="Cài đặt">
            <span className="icon"><I.settings /></span>
          </button>
          <Button variant="secondary" icon={<I.share />} onClick={() => setShowInvite(true)}>
            Mời
          </Button>
          <Button variant="dark" icon={<I.plus />} onClick={() => setShowAddExpense(true)}>
            Thêm khoản chi
          </Button>
        </div>
      </div>

      {(() => {
        // Banner: pending settlements waiting for ME to confirm
        const myPending = settlements.filter(s => s.status === "pending" && s.toUserId === me.id);
        if (myPending.length === 0) return null;
        const total = myPending.reduce((s, x) => s + x.amount, 0);
        return (
          <div style={{
            background: "var(--warning-soft)",
            border: "1px solid var(--warning)",
            color: "var(--warning)",
            padding: "12px 16px",
            borderRadius: "var(--r-lg)",
            marginBottom: 24,
            fontSize: 14,
            display: "flex", alignItems: "center", gap: 12,
            flexWrap: "wrap",
          }}>
            <span className="icon"><I.bell /></span>
            <span style={{ flex: 1, minWidth: 200 }}>
              Có <b>{myPending.length} thanh toán</b> tổng <b>{window.QC.formatVND(total)}</b> đang chờ bạn xác nhận đã nhận.
            </span>
            <Button size="sm" variant="primary" onClick={() => setTab("balances")}>
              Xem & xác nhận
            </Button>
          </div>
        );
      })()}

      <div className="grid-stats" style={{ marginBottom: 24 }}>
        <div className="card card-tight">
          <div className="stat">
            <div className="stat-label">Tổng chi</div>
            <div className="stat-value">{window.QC.formatVND(totalSpent)}</div>
            <div className="stat-meta">{bills.length} khoản chi</div>
          </div>
        </div>
        <div className="card card-tight">
          <div className="stat">
            <div className="stat-label">Tình trạng của bạn</div>
            <div className={"stat-value " + (myBal > 100 ? "money-positive" : myBal < -100 ? "money-negative" : "money-zero")}>
              {Math.abs(myBal) < 100 ? "Đã cân" : window.QC.formatVND(Math.abs(myBal))}
            </div>
            <div className="stat-meta">
              {myBal > 100 ? "Được người khác trả" : myBal < -100 ? "Bạn cần trả" : "Không nợ ai cả"}
            </div>
          </div>
        </div>
        <div className="card card-tight">
          <div className="stat">
            <div className="stat-label">Trung bình / người</div>
            <div className="stat-value">{window.QC.formatVND(totalSpent / Math.max(members.length, 1))}</div>
            <div className="stat-meta">{members.length} thành viên</div>
          </div>
        </div>
      </div>

      <Tabs tabs={[
        { value: "overview",   label: "Tổng quan" },
        { value: "bills",      label: "Khoản chi", count: bills.length },
        { value: "balances",   label: "Ai nợ ai" },
        { value: "members",    label: "Thành viên", count: members.length },
        { value: "activity",   label: "Hoạt động" },
      ]} value={tab} onChange={setTab} />

      {tab === "overview" && (
        <RoomOverview room={room} members={members} bills={bills}
                      balances={balances} transfers={transfers}
                      settlements={settlements}
                      me={me} userById={userById}
                      onSettle={setSettleTransfer} onRemind={remind}
                      onConfirmSettlement={confirmSettlement}
                      onRejectSettlement={rejectSettlement}
                      onAddExpense={() => setShowAddExpense(true)} />
      )}
      {tab === "bills" && (
        <BillsList bills={bills} userById={userById} me={me}
                   onEdit={setEditingBill} onDelete={deleteBill}
                   onAdd={() => setShowAddExpense(true)} />
      )}
      {tab === "balances" && (
        <BalancesPanel balances={balances} transfers={transfers} members={members} me={me}
                       settlements={settlements} userById={userById}
                       onSettle={setSettleTransfer} onRemind={remind}
                       onUndoSettlement={undoSettlement}
                       onConfirmSettlement={confirmSettlement}
                       onRejectSettlement={rejectSettlement} />
      )}
      {tab === "members" && (
        <MembersPanel room={room} members={members} me={me} balances={balances} reload={reload} />
      )}
      {tab === "activity" && (
        <ActivityPanel roomId={room.id} userById={userById} />
      )}

      {(showAddExpense || editingBill) && (
        <ExpenseModal
          open={showAddExpense || !!editingBill}
          onClose={() => { setShowAddExpense(false); setEditingBill(null); }}
          room={room} members={members} me={me}
          editing={editingBill}
          onSaved={() => { refreshAll(); setShowAddExpense(false); setEditingBill(null); }}
        />
      )}

      <InviteModal open={showInvite} onClose={() => setShowInvite(false)} room={room} />

      {settleTransfer && (
        <SettleModal transfer={settleTransfer} userById={userById}
                     onClose={() => setSettleTransfer(null)}
                     onConfirm={performSettle} />
      )}

      <RoomSettingsModal open={showSettings} onClose={() => setShowSettings(false)}
                         room={room} me={me}
                         onUpdated={reload}
                         onDeleted={() => navigate({ screen: "rooms" })}
                         onLeft={() => navigate({ screen: "rooms" })}
                         onExportCSV={exportCSV} />
    </div>
  );
}


// ── Bills list with search + filter + detail modal ────────────────────
function BillsList({ bills, userById, me, onEdit, onDelete, onAdd }) {
  const [query, setQuery] = React.useState("");
  const [modeFilter, setModeFilter] = React.useState("");
  const [detailBill, setDetailBill] = React.useState(null);

  if (bills.length === 0) {
    return <Empty icon={<I.receipt />} title="Chưa có khoản chi nào"
                  action={<Button variant="primary" icon={<I.plus />} onClick={onAdd}>Thêm khoản chi đầu tiên</Button>}>
      Bắt đầu bằng cách ghi lại bill ăn tối, vé xe, hoặc bất kỳ chi phí chung nào.
    </Empty>;
  }

  const q = query.trim().toLowerCase();
  const filtered = bills.filter(b => {
    if (modeFilter && b.splitMode !== modeFilter) return false;
    if (!q) return true;
    const payer = userById(b.paidById)?.name.toLowerCase() || "";
    return b.title.toLowerCase().includes(q)
      || (b.note || "").toLowerCase().includes(q)
      || payer.includes(q);
  });

  const groups = {};
  filtered.forEach(b => {
    const d = new Date(b.createdAt);
    const key = `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
    (groups[key] = groups[key] || { date: b.createdAt, items: [] }).items.push(b);
  });
  const sorted = Object.values(groups).sort((a, b) => new Date(b.date) - new Date(a.date));

  return (
    <div className="stack stack-lg">
      <div className="row-h" style={{ gap: 10, flexWrap: "wrap" }}>
        <div className="input-prefix" style={{ flex: 1, minWidth: 200 }}>
          <div className="prefix"><span className="icon icon-sm"><I.search /></span></div>
          <input className="input" value={query} onChange={e => setQuery(e.target.value)}
                 placeholder="Tìm khoản chi, người trả, ghi chú..." />
        </div>
        <select className="select" value={modeFilter} onChange={e => setModeFilter(e.target.value)} style={{ width: 180 }}>
          <option value="">Tất cả cách chia</option>
          <option value="equal">Chia đều</option>
          <option value="select">Chọn người</option>
          <option value="amount">Số tiền cụ thể</option>
          <option value="percent">Theo %</option>
          <option value="shares">Theo phần</option>
        </select>
      </div>

      {filtered.length === 0 && <Empty>Không tìm thấy khoản chi nào khớp với bộ lọc.</Empty>}

      {sorted.map((g, gi) => (
        <div key={gi}>
          <div className="section-title">{window.QC.dateLong(g.date).split(" · ")[0]}</div>
          <div className="card" style={{ padding: "4px 16px" }}>
            {g.items.map(bill => {
              const payer = userById(bill.paidById);
              const participants = bill.participantIds.map(userById).filter(Boolean);
              return (
                <div key={bill.id} className="row" style={{ alignItems: "flex-start", cursor: "pointer" }}
                     onClick={() => setDetailBill(bill)}>
                  <div className="activity-icon"><span className="icon"><I.receipt /></span></div>
                  <div className="row-main">
                    <div className="row-h" style={{ gap: 8, flexWrap: "wrap" }}>
                      <span className="row-title">{bill.title}</span>
                      <span className="badge">{splitLabel(bill.splitMode)}</span>
                    </div>
                    <div className="row-sub">
                      <span className="fw-600 text-fg-2">{payer?.name || "—"}</span> đã trả · {participants.length} người chia
                      {bill.note && <> · <i>{bill.note}</i></>}
                    </div>
                    <div style={{ marginTop: 6 }}><AvatarStack users={participants} max={5} /></div>
                  </div>
                  <div className="row-aside" onClick={e => e.stopPropagation()}>
                    <div className="money" style={{ fontSize: 16 }}>{window.QC.formatVND(bill.totalAmount)}</div>
                    {bill.createdBy === me.id && (
                      <div className="row-h" style={{ gap: 4, justifyContent: "flex-end", marginTop: 4 }}>
                        <button className="btn btn-ghost btn-sm btn-icon" onClick={() => onEdit(bill)} title="Sửa">
                          <span className="icon icon-sm"><I.edit /></span>
                        </button>
                        <button className="btn btn-danger-ghost btn-sm btn-icon" onClick={() => onDelete(bill.id)} title="Xoá">
                          <span className="icon icon-sm"><I.trash /></span>
                        </button>
                      </div>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      ))}

      {detailBill && (
        <BillDetailModal bill={detailBill} userById={userById} me={me}
                         onClose={() => setDetailBill(null)}
                         onEdit={() => { onEdit(detailBill); setDetailBill(null); }}
                         onDelete={() => { onDelete(detailBill.id); setDetailBill(null); }} />
      )}
    </div>
  );
}


function BillDetailModal({ bill, userById, me, onClose, onEdit, onDelete }) {
  const payer = userById(bill.paidById);
  const participants = bill.participantIds.map(userById).filter(Boolean);
  const splits = window.QC.splitToAmounts(bill);
  const myShare = splits[me.id] || 0;
  const isCreator = bill.createdBy === me.id;
  const creator = userById(bill.createdBy);

  const shareForRow = (uid) => {
    if (bill.splitMode === "percent") return `${bill.shares?.[uid] || 0}%`;
    if (bill.splitMode === "shares")  return `${bill.shares?.[uid] || 0} phần`;
    return "";
  };

  return (
    <Modal open={true} onClose={onClose} title={bill.title}
           footer={<>
             <Button variant="ghost" onClick={onClose}>Đóng</Button>
             {isCreator && <Button variant="secondary" icon={<I.edit />} onClick={onEdit}>Sửa</Button>}
             {isCreator && <Button variant="ghost" onClick={onDelete} style={{ color: "var(--danger)" }}>Xoá</Button>}
           </>}>
      <div className="stack stack-md">
        <div className="row-h-between" style={{ background: "var(--wf-bg-subtle)", padding: 16, borderRadius: "var(--r-lg)" }}>
          <div>
            <div className="text-xs text-muted">Tổng</div>
            <div style={{ fontSize: 26, fontWeight: 700, fontVariantNumeric: "tabular-nums" }}>
              {window.QC.formatVND(bill.totalAmount)}
            </div>
            <div className="text-xs text-muted" style={{ marginTop: 4 }}>
              {window.QC.dateLong(bill.createdAt)}
            </div>
          </div>
          <div style={{ textAlign: "right" }}>
            <div className="text-xs text-muted">Cách chia</div>
            <div className="fw-700">{splitLabel(bill.splitMode)}</div>
          </div>
        </div>
        <div>
          <div className="row-h" style={{ gap: 12, padding: "8px 0" }}>
            <Avatar user={payer} />
            <div style={{ flex: 1 }}>
              <div className="row-title">{payer?.name} đã ứng trước</div>
              <div className="row-sub">Người trả · {window.QC.formatVND(bill.totalAmount)}</div>
            </div>
            <div className="money money-positive">+{window.QC.formatVND(bill.totalAmount)}</div>
          </div>
        </div>
        <div>
          <div className="section-title">Chia cho</div>
          {participants.map(p => {
            const share = splits[p.id] || 0;
            return (
              <div key={p.id} className="row">
                <Avatar user={p} size="sm" />
                <div className="row-main">
                  <div className="row-title">
                    {p.name}{p.id === me.id && <span className="text-muted text-xs"> (bạn)</span>}
                  </div>
                  {shareForRow(p.id) && <div className="row-sub">{shareForRow(p.id)}</div>}
                </div>
                <div className="money money-negative">−{window.QC.formatVND(share)}</div>
              </div>
            );
          })}
        </div>
        {bill.note && (
          <div style={{ background: "var(--wf-bg-subtle)", padding: 12, borderRadius: "var(--r-md)" }}>
            <div className="text-xs text-muted fw-600" style={{ marginBottom: 4 }}>GHI CHÚ</div>
            <div className="text-sm text-fg-2">{bill.note}</div>
          </div>
        )}
        {creator && creator.id !== bill.paidById && (
          <div className="text-xs text-muted">
            Tạo bởi <b>{creator.name}</b> · {!isCreator && "(chỉ người tạo mới được sửa/xoá)"}
          </div>
        )}
        {!isCreator && (
          <div className="text-xs text-muted">
            <span className="icon icon-sm"><I.user /></span>{" "}
            Bạn không phải người tạo khoản chi này — không thể sửa hoặc xoá.
          </div>
        )}
        {me.id !== bill.paidById && bill.participantIds.includes(me.id) && (
          <div style={{ background: "var(--accent-soft)", padding: "10px 14px", borderRadius: "var(--r-md)", fontSize: 14, color: "var(--accent-active)" }}>
            Phần của bạn trong khoản này: <b>{window.QC.formatVND(myShare)}</b>
          </div>
        )}
      </div>
    </Modal>
  );
}


// ── Overview ───────────────────────────────────────────────────────────
function RoomOverview({ room, members, bills, balances, transfers, settlements, me, userById, onSettle, onRemind, onConfirmSettlement, onRejectSettlement, onAddExpense }) {
  const recent = bills.slice().sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)).slice(0, 4);
  const memberSpent = {};
  members.forEach(m => memberSpent[m.id] = 0);
  bills.forEach(b => memberSpent[b.paidById] = (memberSpent[b.paidById] || 0) + b.totalAmount);

  return (
    <div className="grid-2">
      <div className="stack stack-lg">
        <div className="card">
          <div className="row-h-between" style={{ marginBottom: 12 }}>
            <div className="section-title" style={{ margin: 0 }}>Khoản chi gần đây</div>
            <a onClick={onAddExpense} style={{ fontSize: 13, fontWeight: 600, cursor: "pointer" }}>+ Thêm</a>
          </div>
          {recent.length === 0 ? (
            <div className="text-sm text-muted">Chưa có khoản chi nào.</div>
          ) : recent.map(bill => {
            const payer = userById(bill.paidById);
            return (
              <div key={bill.id} className="row">
                <div className="activity-icon"><span className="icon"><I.receipt /></span></div>
                <div className="row-main">
                  <div className="row-title">{bill.title}</div>
                  <div className="row-sub">{payer?.name} · {window.QC.timeAgo(bill.createdAt)}</div>
                </div>
                <div className="money">{window.QC.formatVND(bill.totalAmount)}</div>
              </div>
            );
          })}
        </div>
        <div className="card">
          <div className="section-title">Ai chi nhiều nhất</div>
          <BarList items={Object.entries(memberSpent)
            .map(([id, v]) => ({ label: userById(id)?.name || "—", value: v }))
            .sort((a, b) => b.value - a.value)} />
        </div>
      </div>

      <div className="stack stack-lg">
        <div className="card">
          <div className="section-title">Ai cần trả ai</div>
          {transfers.length === 0 ? (
            <div className="text-sm text-muted" style={{ padding: "8px 0" }}>Phòng đã cân bằng, không ai nợ ai.</div>
          ) : transfers.map((t, i) => {
            const from = userById(t.fromUserId);
            const to = userById(t.toUserId);
            const iAmDebtor = t.fromUserId === me.id;
            const iAmCreditor = t.toUserId === me.id;
            const pending = (settlements || []).some(s =>
              s.status === "pending" && s.fromUserId === t.fromUserId && s.toUserId === t.toUserId
            );
            return (
              <div key={i} className="balance-row">
                <div className="balance-arrow">
                  <Avatar user={from} size="sm" />
                  <span className="name">{from?.name}</span>
                  <span className="icon icon-sm"><I.arrowRight /></span>
                  <Avatar user={to} size="sm" />
                  <span className="name">{to?.name}</span>
                  {pending && <span className="badge badge-warning">Đang chờ</span>}
                </div>
                <div className="money" style={{ fontSize: 14 }}>{window.QC.formatVND(t.amount)}</div>
                {iAmDebtor && !pending && (
                  <Button size="sm" variant="primary" onClick={() => onSettle(t)}>Trả</Button>
                )}
                {iAmCreditor && !pending && (
                  <Button size="sm" variant="ghost" icon={<I.bell />} onClick={() => onRemind(t)}>Nhắc</Button>
                )}
              </div>
            );
          })}
        </div>

        <div className="card">
          <div className="section-title">Thành viên</div>
          {members.map(m => {
            const bal = balances[m.id] || 0;
            return (
              <div key={m.id} className="row">
                <Avatar user={m} />
                <div className="row-main">
                  <div className="row-title">{m.name} {m.id === me.id && <span className="text-muted text-xs">(bạn)</span>}</div>
                  <div className="row-sub">{bal > 100 ? "Được trả" : bal < -100 ? "Đang nợ" : "Đã cân"}</div>
                </div>
                <div className={"money " + (bal > 100 ? "money-positive" : bal < -100 ? "money-negative" : "money-zero")}>
                  {Math.abs(bal) < 100 ? "0 ₫" : (bal > 0 ? "+" : "−") + window.QC.formatVND(Math.abs(bal)).replace("-", "")}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}


function BalancesPanel({ balances, transfers, members, me, settlements, userById, onSettle, onRemind, onUndoSettlement, onConfirmSettlement, onRejectSettlement }) {
  return (
    <div className="stack stack-lg">
      <div className="grid-2">
      <div className="card">
        <div className="section-title">Net balance mỗi người</div>
        {Object.entries(balances)
          .map(([id, bal]) => ({ user: userById(id), bal }))
          .filter((x) => x.user)
          .sort((a, b) => b.bal - a.bal)
          .map(({ user, bal }) => (
            <div key={user.id} className="row">
              <Avatar user={user} />
              <div className="row-main">
                <div className="row-title">{user.name} {user.id === me.id && <span className="text-muted text-xs">(bạn)</span>}</div>
                <div className="row-sub">
                  {bal > 100 ? "Người khác đang nợ" : bal < -100 ? "Đang nợ người khác" : "Đã cân"}
                </div>
              </div>
              <div className={"money " + (bal > 100 ? "money-positive" : bal < -100 ? "money-negative" : "money-zero")}>
                {Math.abs(bal) < 100 ? "0 ₫" : (bal > 0 ? "+" : "−") + window.QC.formatVND(Math.abs(bal)).replace("-", "")}
              </div>
            </div>
          ))}
      </div>
      <div className="card">
        <div className="row-h-between" style={{ marginBottom: 6 }}>
          <div className="section-title" style={{ margin: 0 }}>Thanh toán gợi ý</div>
          <span className="badge">Tối giản</span>
        </div>
        <div className="text-xs text-muted" style={{ marginBottom: 12 }}>
          Số giao dịch nhỏ nhất để cân bằng phòng. Chỉ <b>người nợ</b> mới bấm xác nhận trả được.
        </div>
        {transfers.length === 0 ? (
          <div className="text-sm text-fg-2" style={{ padding: "16px 0" }}>
            Đã cân bằng. Không cần thanh toán gì.
          </div>
        ) : transfers.map((t, i) => {
          const from = userById(t.fromUserId);
          const to = userById(t.toUserId);
          const iAmDebtor = t.fromUserId === me.id;
          const iAmCreditor = t.toUserId === me.id;
          const pending = (settlements || []).some(s =>
            s.status === "pending" && s.fromUserId === t.fromUserId && s.toUserId === t.toUserId
          );
          return (
            <div key={i} className="balance-row">
              <div className="balance-arrow">
                <Avatar user={from} size="sm" />
                <span className="name">{from?.name}</span>
                <span className="icon icon-sm"><I.arrowRight /></span>
                <Avatar user={to} size="sm" />
                <span className="name">{to?.name}</span>
                {pending && <span className="badge badge-warning">Đang chờ xác nhận</span>}
              </div>
              <div className="money">{window.QC.formatVND(t.amount)}</div>
              {iAmDebtor && !pending && (
                <Button size="sm" variant="primary" onClick={() => onSettle(t)}>Trả ngay</Button>
              )}
              {iAmDebtor && pending && (
                <span className="text-xs text-muted" style={{ minWidth: 90, textAlign: "right" }}>
                  Chờ {to?.name?.split(" ").pop()} xác nhận
                </span>
              )}
              {iAmCreditor && (
                <Button size="sm" variant="ghost" icon={<I.bell />} onClick={() => onRemind(t)}>Nhắc</Button>
              )}
              {!iAmDebtor && !iAmCreditor && (
                <span className="text-xs text-muted">—</span>
              )}
            </div>
          );
        })}
      </div>
      </div>

      {/* Lịch sử thanh toán (settlements) — undo nếu cần (bug fix #3) */}
      <div className="card">
        <div className="row-h-between" style={{ marginBottom: 6 }}>
          <div className="section-title" style={{ margin: 0 }}>Lịch sử thanh toán</div>
          <span className="text-xs text-muted">
            {settlements && settlements.length > 0
              ? `${settlements.length} lần`
              : "Chưa có"}
          </span>
        </div>
        <div className="text-xs text-muted" style={{ marginBottom: 12 }}>
          Người nợ <b>đánh dấu đã trả</b> → người nhận <b>xác nhận</b> mới ghi vào sổ.
          Lỡ rồi có thể huỷ để tính lại.
        </div>
        {(!settlements || settlements.length === 0) ? (
          <div className="text-sm text-muted" style={{ padding: "8px 0" }}>
            Chưa có ai trả nợ trong phòng này.
          </div>
        ) : settlements.slice().sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)).map(s => {
          const from = userById(s.fromUserId);
          const to = userById(s.toUserId);
          const pending = s.status === "pending";
          const iAmCreditor = s.toUserId === me.id;
          const iAmCreator  = s.createdBy === me.id;

          return (
            <div key={s.id} className="balance-row" style={pending ? { background: "var(--warning-soft)", margin: "0 -8px", padding: "10px 8px", borderRadius: "var(--r-md)" } : {}}>
              <div className="balance-arrow" style={{ flexWrap: "wrap" }}>
                <Avatar user={from} size="sm" />
                <span className="name">{from?.name}</span>
                <span className="icon icon-sm"><I.arrowRight /></span>
                <Avatar user={to} size="sm" />
                <span className="name">{to?.name}</span>
                {pending
                  ? <span className="badge badge-warning">Đang chờ xác nhận</span>
                  : <span className="badge badge-success">Đã xác nhận</span>}
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="money">{window.QC.formatVND(s.amount)}</div>
                <div className="text-xs text-muted">{window.QC.timeAgo(s.createdAt)}</div>
              </div>
              <div className="row-h" style={{ gap: 4, justifyContent: "flex-end", minWidth: 90 }}>
                {pending && iAmCreditor && (
                  <>
                    <Button size="sm" variant="primary" icon={<I.check />}
                            onClick={() => onConfirmSettlement(s.id)}>Đã nhận</Button>
                    <Button size="sm" variant="ghost"
                            onClick={() => onRejectSettlement(s.id)}
                            style={{ color: "var(--danger)" }}>Từ chối</Button>
                  </>
                )}
                {pending && iAmCreator && !iAmCreditor && (
                  <Button size="sm" variant="ghost" icon={<I.trash />}
                          onClick={() => onUndoSettlement(s.id)}>Huỷ</Button>
                )}
                {!pending && iAmCreator && (
                  <Button size="sm" variant="ghost" icon={<I.trash />}
                          onClick={() => onUndoSettlement(s.id)} title="Huỷ thanh toán này">
                    Huỷ
                  </Button>
                )}
                {!pending && !iAmCreator && (
                  <span className="text-xs text-muted">—</span>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}


function MembersPanel({ room, members, me, balances, reload }) {
  const isOwner = me.id === room.ownerId;
  const toast = useToast();

  const removeMember = async (userId) => {
    if (userId === room.ownerId) { toast("Không thể xoá chủ phòng"); return; }
    if (!confirm("Xoá thành viên này khỏi phòng?")) return;
    try {
      await window.api.rooms.removeMember(room.id, userId);
      toast("Đã xoá thành viên");
      reload();
    } catch (err) { toast(err.message); }
  };

  return (
    <div className="card">
      {members.map(m => {
        const isRoomOwner = m.id === room.ownerId;
        const bal = balances[m.id] || 0;
        return (
          <div key={m.id} className="row">
            <Avatar user={m} size="lg" />
            <div className="row-main">
              <div className="row-h" style={{ gap: 8 }}>
                <span className="fw-600">{m.name}</span>
                {m.id === me.id && <span className="badge">Bạn</span>}
                {isRoomOwner && <span className="badge badge-accent">Chủ phòng</span>}
              </div>
              <div className="row-sub">{m.email} {m.phone && <>· {m.phone}</>}</div>
              {m.bankCode && m.bankAccount && (
                <div className="text-xs text-muted" style={{ marginTop: 4 }}>
                  {window.QC.VN_BANKS.find(b => b.code === m.bankCode)?.name} · <span className="mono">{m.bankAccount}</span>
                </div>
              )}
            </div>
            <div style={{ textAlign: "right" }}>
              <div className={"money " + (bal > 100 ? "money-positive" : bal < -100 ? "money-negative" : "money-zero")}>
                {Math.abs(bal) < 100 ? "0 ₫" : (bal > 0 ? "+" : "−") + window.QC.formatVND(Math.abs(bal)).replace("-", "")}
              </div>
              {isOwner && !isRoomOwner && (
                <button className="btn btn-danger-ghost btn-sm" style={{ marginTop: 4 }} onClick={() => removeMember(m.id)}>Xoá</button>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}


function ActivityPanel({ roomId, userById }) {
  const { data, loading, error, reload } = useApi(() => window.api.rooms.notifications(roomId), [roomId]);
  if (loading) return <LoadingState />;
  if (error) return <ErrorState error={error} onRetry={reload} />;
  const items = data.notifications;
  if (items.length === 0) return <Empty icon={<I.inbox />} title="Chưa có hoạt động">Khi có người thêm bill / thanh toán, hoạt động sẽ hiện ở đây.</Empty>;
  return (
    <div className="card">
      {items.map((n, i) => (
        <div key={n.id || i} className="activity-item">
          <div className="activity-icon">
            <span className="icon">
              {n.type === "settle" ? <I.handshake /> :
               n.type === "expense" ? <I.receipt /> :
               n.type === "join" ? <I.users /> :
               n.type === "remind" ? <I.bell /> :
               n.type === "leave" ? <I.logout /> :
               n.type === "create" ? <I.doorOpen /> :
               n.type === "delete" ? <I.trash /> :
               <I.bell />}
            </span>
          </div>
          <div className="activity-body">
            <div className="activity-text">{n.text}</div>
            <div className="activity-meta">{window.QC.dateLong(n.createdAt)}</div>
          </div>
        </div>
      ))}
    </div>
  );
}


function SettleModal({ transfer, userById, onClose, onConfirm }) {
  const from = userById(transfer.fromUserId);
  const to = userById(transfer.toUserId);
  const [submitting, setSubmitting] = React.useState(false);
  const qr = to ? window.QC.vietQRUrl({
    bankCode: to.bankCode, accountNo: to.bankAccount, accountName: to.accountHolder,
    amount: transfer.amount, addInfo: "Quy chung " + (from?.name || ""),
  }) : null;

  return (
    <Modal open={true} onClose={onClose} title="Thanh toán"
           footer={<>
             <Button variant="ghost" onClick={onClose}>Huỷ</Button>
             <Button variant="primary" icon={<I.check />} disabled={submitting}
                     onClick={async () => { setSubmitting(true); try { await onConfirm(transfer); } finally { setSubmitting(false); } }}>
               {submitting ? "Đang lưu..." : "Tôi đã trả — chờ xác nhận"}
             </Button>
           </>}>
      <div className="stack stack-md">
        <div className="row-h" style={{ justifyContent: "center", gap: 16 }}>
          <div style={{ textAlign: "center" }}>
            <Avatar user={from} size="lg" />
            <div className="text-sm fw-600" style={{ marginTop: 6 }}>{from?.name}</div>
            <div className="text-xs text-muted">Người trả</div>
          </div>
          <span className="icon icon-lg text-muted"><I.arrowRight /></span>
          <div style={{ textAlign: "center" }}>
            <Avatar user={to} size="lg" />
            <div className="text-sm fw-600" style={{ marginTop: 6 }}>{to?.name}</div>
            <div className="text-xs text-muted">Người nhận</div>
          </div>
        </div>
        <div style={{ textAlign: "center", padding: "16px 0", borderTop: "1px solid var(--wf-border)", borderBottom: "1px solid var(--wf-border)" }}>
          <div className="text-xs text-muted">Số tiền</div>
          <div style={{ fontSize: 28, fontWeight: 700, marginTop: 4, fontVariantNumeric: "tabular-nums" }}>
            {window.QC.formatVND(transfer.amount)}
          </div>
        </div>
        {qr ? (
          <div className="row-h" style={{ alignItems: "flex-start", gap: 16 }}>
            <div className="qr-frame"><img src={qr} alt="VietQR" /></div>
            <div style={{ flex: 1, fontSize: 13 }}>
              <div className="fw-600 text-fg" style={{ marginBottom: 4 }}>Quét QR để chuyển khoản</div>
              <div className="text-muted" style={{ marginBottom: 12 }}>
                Mở app ngân hàng → quét QR → số tiền và nội dung đã được điền sẵn.
              </div>
              <div className="text-xs text-muted">Ngân hàng</div>
              <div className="fw-600">{window.QC.VN_BANKS.find(b => b.code === to?.bankCode)?.name}</div>
              <div className="text-xs text-muted" style={{ marginTop: 8 }}>Số tài khoản</div>
              <div className="mono fw-600">{to?.bankAccount}</div>
              <div className="text-xs text-muted" style={{ marginTop: 8 }}>Chủ tài khoản</div>
              <div className="fw-600">{to?.accountHolder}</div>
            </div>
          </div>
        ) : (
          <div style={{ background: "var(--warning-soft)", color: "var(--warning)", padding: 12, borderRadius: "var(--r-md)", fontSize: 13 }}>
            <b>{to?.name}</b> chưa thêm thông tin ngân hàng. Hãy nhắc bạn ấy cập nhật trang cá nhân.
          </div>
        )}

        <div style={{ background: "var(--accent-soft)", color: "var(--accent-active)", padding: 12, borderRadius: "var(--r-md)", fontSize: 13 }}>
          Sau khi bấm xác nhận, <b>{to?.name}</b> sẽ phải xác nhận đã nhận được tiền thì khoản nợ mới được xoá. Tránh nhầm lẫn 2 chiều.
        </div>
      </div>
    </Modal>
  );
}


// ── Invite modal with both code + shareable link ─────────────────────
function InviteModal({ open, onClose, room }) {
  const toast = useToast();
  const link = `${location.origin}${location.pathname}?join=${room.code}`;

  const copy = (text, label) => {
    navigator.clipboard?.writeText(text);
    toast("Đã copy " + label);
  };

  return (
    <Modal open={open} onClose={onClose} title="Mời thành viên"
           footer={<Button variant="secondary" onClick={onClose}>Đóng</Button>}>
      <div className="stack stack-md">
        <div>
          <div className="field-label" style={{ marginBottom: 6 }}>Mã phòng</div>
          <div style={{ background: "var(--wf-bg-subtle)", border: "1px solid var(--wf-border)", borderRadius: "var(--r-lg)", padding: 20, textAlign: "center" }}>
            <div className="mono fw-700" style={{ fontSize: 32, letterSpacing: "0.2em" }}>
              {room.code}
            </div>
            <button className="btn btn-secondary btn-sm" style={{ marginTop: 12 }}
                    onClick={() => copy(room.code, "mã")}>
              <span className="icon icon-sm"><I.copy /></span> Copy mã
            </button>
          </div>
        </div>

        <div>
          <div className="field-label" style={{ marginBottom: 6 }}>Hoặc chia sẻ link</div>
          <div className="input-prefix">
            <div className="prefix"><span className="icon icon-sm"><I.link /></span></div>
            <input className="input mono" readOnly value={link} style={{ fontSize: 12 }} />
            <button className="btn btn-ghost btn-sm" style={{ borderRadius: 0 }}
                    onClick={() => copy(link, "link")}>
              Copy
            </button>
          </div>
          <div className="text-xs text-muted" style={{ marginTop: 6 }}>
            Bất kỳ ai mở link này (sau khi đăng nhập) sẽ tự động vào phòng.
          </div>
        </div>

        <div>
          <div className="field-label" style={{ marginBottom: 6 }}>Mời nhanh qua</div>
          <div className="row-h" style={{ gap: 8, flexWrap: "wrap" }}>
            <a className="btn btn-secondary btn-sm"
               href={`https://zalo.me/share/url?url=${encodeURIComponent(link)}`}
               target="_blank" rel="noopener">
              Zalo
            </a>
            <a className="btn btn-secondary btn-sm"
               href={`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(link)}`}
               target="_blank" rel="noopener">
              Facebook
            </a>
            <a className="btn btn-secondary btn-sm"
               href={`mailto:?subject=${encodeURIComponent("Vào phòng " + room.name + " trên Tachiara")}&body=${encodeURIComponent("Mã phòng: " + room.code + "\nLink: " + link)}`}>
              Email
            </a>
            <a className="btn btn-secondary btn-sm"
               href={`sms:?&body=${encodeURIComponent("Vào phòng \"" + room.name + "\" trên Tachiara: " + link)}`}>
              SMS
            </a>
          </div>
        </div>
      </div>
    </Modal>
  );
}


function RoomSettingsModal({ open, onClose, room, me, onUpdated, onDeleted, onLeft, onExportCSV }) {
  const isOwner = me.id === room.ownerId;
  const [name, setName] = React.useState(room.name);
  const [desc, setDesc] = React.useState(room.description || "");
  const [submitting, setSubmitting] = React.useState(false);
  const toast = useToast();

  React.useEffect(() => { if (open) { setName(room.name); setDesc(room.description || ""); } }, [open, room.id]);

  const save = async () => {
    if (!name.trim()) return;
    setSubmitting(true);
    try {
      await window.api.rooms.update(room.id, { name: name.trim(), description: desc.trim() });
      toast("Đã lưu"); onUpdated(); onClose();
    } catch (err) { toast(err.message); }
    finally { setSubmitting(false); }
  };

  const leaveRoom = async () => {
    if (isOwner) { toast("Chủ phòng không thể rời. Hãy xoá phòng."); return; }
    if (!confirm(`Rời khỏi phòng "${room.name}"?`)) return;
    try {
      await window.api.rooms.leave(room.id);
      toast("Đã rời phòng");
      onLeft();
    } catch (err) { toast(err.message); }
  };

  const deleteRoom = async () => {
    if (!isOwner) return;
    if (!confirm(`Xoá phòng "${room.name}" cùng toàn bộ khoản chi? Không thể hoàn tác.`)) return;
    try {
      await window.api.rooms.delete(room.id);
      toast("Đã xoá phòng");
      onDeleted();
    } catch (err) { toast(err.message); }
  };

  return (
    <Modal open={open} onClose={onClose} title="Cài đặt phòng"
           footer={<>
             <Button variant="ghost" onClick={onClose}>Đóng</Button>
             {isOwner && <Button variant="primary" onClick={save} disabled={!name.trim() || submitting}>Lưu thay đổi</Button>}
           </>}>
      <div className="stack stack-md">
        {isOwner ? (
          <>
            <Field label="Tên phòng">
              <input className="input" value={name} onChange={e => setName(e.target.value)} />
            </Field>
            <Field label="Mô tả">
              <textarea className="textarea" value={desc} onChange={e => setDesc(e.target.value)} placeholder="Ngắn gọn về phòng" />
            </Field>
          </>
        ) : (
          <div>
            <div className="text-sm text-fg-2"><b>{room.name}</b></div>
            {room.description && <div className="text-sm text-muted" style={{ marginTop: 4 }}>{room.description}</div>}
            <div className="text-xs text-muted" style={{ marginTop: 8 }}>Chỉ chủ phòng mới sửa được thông tin.</div>
          </div>
        )}

        <hr className="divider" />

        <div>
          <div className="section-title">Xuất dữ liệu</div>
          <div className="row-h-between">
            <div>
              <div className="row-title">Tải xuống file CSV</div>
              <div className="row-sub">Server-side export, mở được bằng Excel / Google Sheets</div>
            </div>
            <Button variant="secondary" icon={<I.share />} onClick={onExportCSV}>Tải CSV</Button>
          </div>
        </div>

        <hr className="divider" />

        <div>
          <div className="section-title" style={{ color: "var(--danger)" }}>Nguy hiểm</div>
          {!isOwner ? (
            <div className="row-h-between">
              <div>
                <div className="row-title">Rời khỏi phòng</div>
                <div className="row-sub">Bạn sẽ không còn thấy phòng này</div>
              </div>
              <Button variant="ghost" onClick={leaveRoom} style={{ color: "var(--danger)" }}>Rời phòng</Button>
            </div>
          ) : (
            <div className="row-h-between">
              <div>
                <div className="row-title">Xoá phòng</div>
                <div className="row-sub">Xoá toàn bộ khoản chi, thanh toán & lịch sử</div>
              </div>
              <Button variant="ghost" onClick={deleteRoom} style={{ color: "var(--danger)" }}>Xoá phòng</Button>
            </div>
          )}
        </div>
      </div>
    </Modal>
  );
}

Object.assign(window, {
  RoomScreen, BillsList, BillDetailModal, RoomOverview, BalancesPanel,
  MembersPanel, ActivityPanel, SettleModal, RoomSettingsModal,
});
