// ===========================================================
// Customers screen — list + filters, opens Customer 360 drawer
// Role-aware: telesale role sees "Khách của tôi" + follow-up calendar
// ===========================================================

// Chủ khách hàng (nhân viên chăm). Ưu tiên owner THẬT từ backend (_owner),
// fallback round-robin cho dữ liệu demo cũ.
const OWNERS = ['Nguyễn Mỹ Linh', 'Trần Quốc Bảo', 'Lê Phương Anh'];
function ownerOf(custId) {
  const D = window.TVS_DATA;
  if (D && D.customers) {
    const c = D.customers.find(x => x.id === custId || x.code === custId);
    if (c && c._owner) return c._owner;
  }
  const n = parseInt(String(custId).replace(/[^0-9]/g, ''), 10) || 0;
  return OWNERS[n % OWNERS.length];
}
window.ownerOf = ownerOf;

// Simple session store for notes & follow-ups — persisted to localStorage
// so demo data survives page refresh. In production this is a real backend.
const __TVS_STORE_KEY = 'tvs_crm_session_v1';
function __loadSession() {
  try {
    const raw = localStorage.getItem(__TVS_STORE_KEY);
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return { notesByCustomer: {}, followupsByCustomer: {}, ordersByCustomer: {} };
}
window.TVS_SESSION = window.TVS_SESSION || Object.assign({ notesByCustomer: {}, followupsByCustomer: {}, ordersByCustomer: {} }, __loadSession(), { _listeners: new Set() });
window.TVS_SESSION._persist = function() {
  try {
    localStorage.setItem(__TVS_STORE_KEY, JSON.stringify({
      notesByCustomer: this.notesByCustomer,
      followupsByCustomer: this.followupsByCustomer,
      ordersByCustomer: this.ordersByCustomer,
    }));
  } catch (e) {}
};
window.TVS_SESSION.subscribe = function(fn) {
  this._listeners.add(fn);
  return () => this._listeners.delete(fn);
};
window.TVS_SESSION.emit = function() {
  this._persist();
  this._listeners.forEach(fn => fn());
};
// Ghi về backend nếu đã đăng nhập thật (fire-and-forget, không chặn UI).
window.TVS_SESSION._push = function(fn) {
  try {
    if (window.TVS_API && window.TVS_API.isAuthed()) {
      Promise.resolve(fn()).catch((e) => console.warn('[TVS_API] lưu thất bại:', e.message));
    }
  } catch (e) {}
};
window.TVS_SESSION.addNote = function(custId, payload) {
  if (!this.notesByCustomer[custId]) this.notesByCustomer[custId] = [];
  this.notesByCustomer[custId].unshift({ id: 'N-' + Date.now(), ...payload, when: 'Vừa xong' });
  this._push(() => window.TVS_API.addNote(custId, { body: payload.text, tag: payload.tag }));
  this.emit();
};
window.TVS_SESSION.addFollowUp = function(custId, payload) {
  if (!this.followupsByCustomer[custId]) this.followupsByCustomer[custId] = [];
  this.followupsByCustomer[custId].unshift({ id: 'F-' + Date.now(), ...payload, createdAt: 'Vừa xong' });
  this._push(() => window.TVS_API.addFollowUp(custId, { reason: payload.reason, date: payload.date, time: payload.time, channel: payload.channel }));
  this.emit();
};
window.TVS_SESSION.addLoggedOrder = function(custId, payload) {
  if (!this.ordersByCustomer) this.ordersByCustomer = {};
  if (!this.ordersByCustomer[custId]) this.ordersByCustomer[custId] = [];
  this.ordersByCustomer[custId].unshift({ id: 'LO-' + Date.now(), ...payload, when: 'Vừa xong', status: 'pending' });
  this._push(() => window.TVS_API.addOrder(custId, { ref: payload.ref, total: payload.total, channel: payload.channel, date: payload.date }));
  this.emit();
};
function useTvsSession() {
  const [, setN] = useState(0);
  useEffect(() => window.TVS_SESSION.subscribe(() => setN(n => n+1)), []);
  return window.TVS_SESSION;
}

function CustomersScreen({ role, onOpenCustomer, onGoToTelesale, onLogOrder, onAddCustomer }) {
  const isTelesale = role.id === 'telesale';
  const isInstore  = role.id === 'instore';
  const isOperator = isTelesale || isInstore;
  const myName = isTelesale ? 'Nguyễn Mỹ Linh' : isInstore ? 'Trần Quốc Bảo' : null;

  // Quick-action popups (note / follow-up)
  const [quickAction, setQuickAction] = useState(null); // { type: 'note'|'followup', customer }

  const [search, setSearch] = useState('');
  const [tierFilter, setTierFilter] = useState('all');
  const [segment, setSegment] = useState(isOperator ? 'mine' : 'all');
  const [view, setView] = useState('list'); // list | followups | pipeline

  const data = useMemo(() => {
    let r = D.customers;
    if (segment === 'mine' && myName)    r = r.filter(c => ownerOf(c.id) === myName);
    if (segment === 'atrisk')  r = r.filter(c => c.tags.includes('At-risk'));
    if (segment === 'new')     r = r.filter(c => c.tags.includes('New'));
    if (segment === 'vip')     r = r.filter(c => c.tier === 'Platinum' || c.tier === 'Gold');
    if (segment === 'followup')r = r.filter(c => c.followUp);
    if (tierFilter !== 'all') r = r.filter(c => c.tier.toLowerCase() === tierFilter);
    if (search) {
      const s = search.toLowerCase();
      r = r.filter(c => c.name.toLowerCase().includes(s) || c.phone.includes(s) || c.id.toLowerCase().includes(s));
    }
    return r;
  }, [search, tierFilter, segment]);

  // Operator KPIs computed from data
  const myCustomers = myName ? D.customers.filter(c => ownerOf(c.id) === myName) : [];
  const myFollowUpsToday = myCustomers.filter(c => c.followUp && new Date(c.followUp.due) <= D.today);

  return (
    <>
      <div className="page-header">
        <div>
          {isOperator && <div className="eyebrow">{role.team}</div>}
          <h1>{isOperator ? 'Khách của tôi' : 'Khách hàng'}</h1>
          <div className="sub">
            {isOperator
              ? <>Bạn đang phụ trách <b style={{color:'var(--vs-dark-blue)'}}>{myCustomers.length}</b> khách hàng · <b style={{color:'var(--status-sale)'}}>{myFollowUpsToday.length} cần follow-up hôm nay</b></>
              : <>{D.customers.length} khách hàng đang hoạt động · {D.followUps.length} cần follow-up hôm nay</>}
          </div>
        </div>
        <div className="row gap-2">
          {isOperator && (
            <Segmented value={view} options={[
              {value:'list',     label:'Danh sách'},
              {value:'followups',label:'Lịch Follow-up'},
              {value:'pipeline', label:'Pipeline'},
            ]} onChange={setView}/>
          )}
          {!isOperator && <button className="btn btn-secondary" onClick={() => window.tvsDemo('Xuất CSV')}><Icon name="download" size={14}/>Xuất CSV</button>}
          {!isOperator && <button className="btn btn-secondary" onClick={() => window.tvsDemo('Bộ lọc nâng cao')}><Icon name="filter" size={14}/>Bộ lọc nâng cao</button>}
          <button className="btn btn-cta" onClick={onAddCustomer}><Icon name="plus" size={14}/>{isInstore ? 'Đăng ký khách mới' : isTelesale ? 'Thêm vào queue' : 'Thêm khách hàng'}</button>
        </div>
      </div>

      {/* Role-specific KPIs */}
      {isTelesale ? (
        <div className="kpi-grid">
          <KPI feature label="Khách được gán" value={myCustomers.length} sub="Vòng phân chia theo cụm SĐT"/>
          <KPI label="Cần follow-up hôm nay" value={myFollowUpsToday.length} delta={`+${myFollowUpsToday.length} mới`} deltaDir="up"/>
          <KPI label="Đã liên hệ tuần này" value="34" delta="+12% vs tuần trước"/>
          <KPI label="Chốt đơn tháng này" value="18" sub="42.8tr doanh số"/>
        </div>
      ) : isInstore ? (
        <div className="kpi-grid">
          <KPI feature label="Khách của cửa hàng Q.1" value={myCustomers.length} sub="Khu vực quận 1"/>
          <KPI label="Cần follow-up hôm nay" value={myFollowUpsToday.length} delta="+2 mới" deltaDir="up"/>
          <KPI label="Đơn đã ghi nhận (7N)" value="94" sub="Từ POS bên ngoài"/>
          <KPI label="Đăng ký thành viên mới" value="12" delta="+4 tuần này"/>
        </div>
      ) : (
        <div className="kpi-grid">
          <KPI label="Tổng khách hàng" value="2.847" delta="+128 tháng này"/>
          <KPI label="VIP (Gold + Platinum)" value="612" sub="21% danh sách"/>
          <KPI label="Khách nguy cơ rời bỏ" value="84" delta="-12 tuần này" deltaDir="up"/>
          <KPI label="LTV trung bình" value="6.84tr" delta="+8% YoY"/>
        </div>
      )}

      {/* ===== VIEW: LIST ===== */}
      {view === 'list' && (
      <Card pad={false}>
        <div style={{padding:'var(--space-3) var(--space-5)',display:'flex',gap:'var(--space-3)',alignItems:'center',borderBottom:'1px solid var(--border-1)',flexWrap:'wrap'}}>
          <div className="topbar-search" style={{flex:'0 1 320px'}}>
            <Icon name="search" size={14} style={{color:'var(--fg-muted)'}}/>
            <input placeholder="Tên, SĐT, mã khách hàng..." value={search} onChange={(e)=>setSearch(e.target.value)}/>
          </div>
          <Segmented value={segment} options={
            isOperator ? [
              {value:'mine',    label:'Của tôi'},
              {value:'followup',label:'Cần follow-up'},
              {value:'atrisk',  label:'Nguy cơ'},
              {value:'vip',     label:'VIP'},
              {value:'all',     label:'Toàn bộ'},
            ] : [
              {value:'all',   label:'Tất cả'},
              {value:'vip',   label:'VIP'},
              {value:'new',   label:'Khách mới'},
              {value:'atrisk',label:'Nguy cơ'},
            ]
          } onChange={setSegment}/>
          <div className="row gap-1" style={{marginLeft:'auto'}}>
            <span className="text-xs fg-muted">Hạng:</span>
            <Segmented value={tierFilter} options={[
              {value:'all',label:'Hết'},
              {value:'platinum',label:'Bạch kim'},
              {value:'gold',label:'Vàng'},
              {value:'silver',label:'Bạc'},
              {value:'bronze',label:'Đồng'},
            ]} onChange={setTierFilter}/>
          </div>
        </div>
        <div className="table-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <th>Khách hàng</th>
                <th>Hạng</th>
                <th>SĐT</th>
                {!isOperator && <th>Khu vực</th>}
                <th className="num">LTV</th>
                <th>Lần mua cuối</th>
                {isOperator ? <th>Liên hệ cuối</th> : <th>Tags</th>}
                <th>Follow-up</th>
                {isOperator ? <th>Người phụ trách</th> : null}
                {isOperator && <th style={{textAlign:'right'}}>Hành động</th>}
              </tr>
            </thead>
            <tbody>
              {data.map(c => {
                const owner = ownerOf(c.id);
                const isMine = owner === myName;
                return (
                <tr key={c.id} onClick={() => onOpenCustomer(c)}>
                  <td>
                    <div className="row gap-3">
                      <Avatar name={c.name} tier={tierVariant(c.tier)}/>
                      <div>
                        <div className="strong">{c.name}</div>
                        <div className="text-xs fg-muted">{c.id} · {c.gender}, {c.age} · {c.city}</div>
                      </div>
                    </div>
                  </td>
                  <td><Tag variant={tierVariant(c.tier)}>{c.tier}</Tag></td>
                  <td className="tnum text-sm">{c.phone}</td>
                  {!isOperator && <td className="text-sm">{c.city}</td>}
                  <td className="num strong">{fmt.vndFull(c.ltv)}</td>
                  <td className="text-sm fg-muted">{fmt.rel(c.lastOrder)}</td>
                  {isOperator ? (
                    <td className="text-sm fg-muted">
                      {c.id === 'C-10241' ? '3 ngày trước' : c.id === 'C-10498' ? '12 ngày trước' : c.id === 'C-10612' ? '5 ngày trước' : c.id === 'C-10812' ? '7 ngày trước' : '—'}
                    </td>
                  ) : (
                    <td>
                      <div className="row gap-1" style={{flexWrap:'wrap',maxWidth:200}}>
                        {c.tags.slice(0,2).map(t => (
                          <Tag key={t} variant={t === 'At-risk' ? 'danger' : t === 'New' ? 'info' : 'outline'}>{t}</Tag>
                        ))}
                      </div>
                    </td>
                  )}
                  <td>
                    {c.followUp ? (
                      <Tag variant={new Date(c.followUp.due) <= D.today ? 'danger' : 'warning'}>{fmt.rel(c.followUp.due)}</Tag>
                    ) : <span className="text-xs fg-muted">—</span>}
                  </td>
                  {isOperator && (
                    <td>
                      {isMine ? (
                        <Tag variant="info" dot>Bạn</Tag>
                      ) : (
                        <span className="text-xs fg-muted">{owner.split(' ').slice(-2).join(' ')}</span>
                      )}
                    </td>
                  )}
                  {isOperator && (
                    <td onClick={(e) => e.stopPropagation()} style={{textAlign:'right'}}>
                      <div className="row gap-1" style={{justifyContent:'flex-end'}}>
                        {isTelesale && (
                          <button className="btn btn-icon btn-sm btn-cta" title="Gọi ngay" onClick={() => onGoToTelesale && onGoToTelesale(c)}>
                            <Icon name="phone" size={13}/>
                          </button>
                        )}
                        {isInstore && (
                          <button className="btn btn-icon btn-sm btn-cta" title="Ghi nhận đơn hàng" onClick={() => onLogOrder && onLogOrder(c)}>
                            <Icon name="receipt" size={13}/>
                          </button>
                        )}
                        <button className="btn btn-icon btn-sm btn-secondary" title="Đặt lịch follow-up" onClick={() => setQuickAction({type:'followup', customer: c})}>
                          <Icon name="clock" size={13}/>
                        </button>
                        <button className="btn btn-icon btn-sm btn-secondary" title="Ghi chú nhanh" onClick={() => setQuickAction({type:'note', customer: c})}>
                          <Icon name="note" size={13}/>
                        </button>
                        <button className="btn btn-icon btn-sm btn-ghost" title="Xem 360°" onClick={() => onOpenCustomer(c)}>
                          <Icon name="eye" size={13}/>
                        </button>
                      </div>
                    </td>
                  )}
                </tr>
              );})}
            </tbody>
          </table>
        </div>
        <div style={{padding:'var(--space-3) var(--space-5)',display:'flex',justifyContent:'space-between',alignItems:'center',borderTop:'1px solid var(--border-1)'}}>
          <span className="text-sm fg-muted">Hiển thị 1–{data.length} trên {isOperator ? myCustomers.length : D.customers.length}</span>
          <div className="row gap-2">
            <button className="btn btn-secondary btn-sm" disabled><Icon name="chevleft" size={14}/></button>
            <button className="btn btn-cta btn-sm">1</button>
            <button className="btn btn-ghost btn-sm">2</button>
            <button className="btn btn-ghost btn-sm">3</button>
            <button className="btn btn-secondary btn-sm"><Icon name="chevron" size={14}/></button>
          </div>
        </div>
      </Card>
      )}

      {/* ===== VIEW: FOLLOW-UPS CALENDAR (operator) ===== */}
      {view === 'followups' && isOperator && (
        <FollowUpView myName={myName} role={role} onOpenCustomer={onOpenCustomer} onGoToTelesale={onGoToTelesale} onLogOrder={onLogOrder}/>
      )}

      {/* ===== VIEW: PIPELINE (operator) ===== */}
      {view === 'pipeline' && isOperator && (
        <CustomerPipeline myName={myName} onOpenCustomer={onOpenCustomer}/>
      )}

      {/* ===== Quick-action modal ===== */}
      {quickAction && (
        <QuickActionModal
          mode={quickAction.type}
          customer={quickAction.customer}
          role={role}
          onClose={() => setQuickAction(null)}
        />
      )}
    </>
  );
}

// ===== Follow-up calendar / timeline view =====
function FollowUpView({ myName, role, onOpenCustomer, onGoToTelesale, onLogOrder }) {
  const isTelesale = role && role.id === 'telesale';
  const isInstore  = role && role.id === 'instore';
  const myCustomers = D.customers.filter(c => ownerOf(c.id) === myName && c.followUp);
  const groups = {
    overdue: [],
    today: [],
    tomorrow: [],
    week: [],
    later: [],
  };
  myCustomers.forEach(c => {
    const d = new Date(c.followUp.due);
    const diff = Math.round((d - D.today) / 86400000);
    if (diff < 0) groups.overdue.push(c);
    else if (diff === 0) groups.today.push(c);
    else if (diff === 1) groups.tomorrow.push(c);
    else if (diff <= 7) groups.week.push(c);
    else groups.later.push(c);
  });

  // Add some synthetic future follow-ups for visual richness
  const otherCustomers = D.customers.filter(c => ownerOf(c.id) === myName && !c.followUp);
  otherCustomers.slice(0,2).forEach((c, i) => {
    groups.week.push({...c, followUp: { due: `2026-05-${15 + i*2}`, reason: i === 0 ? 'Check-in 30 ngày sau mua' : 'Đề xuất tăng size combo' }});
  });

  const sections = [
    {key:'overdue', label: 'Quá hạn', variant: 'danger',  icon: 'flame'},
    {key:'today',   label: 'Hôm nay', variant: 'danger',  icon: 'flag'},
    {key:'tomorrow',label: 'Ngày mai',variant: 'warning', icon: 'clock'},
    {key:'week',    label: '7 ngày tới', variant: 'info', icon: 'calendar'},
    {key:'later',   label: 'Sau đó',  variant: 'outline', icon: 'calendar'},
  ];

  return (
    <Card pad={false}>
      <CardHeader title="Lịch follow-up của tôi"
        sub={`${myCustomers.length} khách cần liên hệ · sắp xếp theo deadline`}
        actions={
          <div className="row gap-2">
            <Segmented value="list" options={[{value:'list',label:'Danh sách'},{value:'cal',label:'Lịch'}]} onChange={()=>{}}/>
            <button className="btn btn-secondary btn-sm"><Icon name="download" size={12}/>Xuất</button>
          </div>
        }/>
      <div className="card-pad">
        {sections.map(s => {
          if (groups[s.key].length === 0) return null;
          return (
            <div key={s.key} style={{marginBottom: 24}}>
              <div className="row mb-3" style={{gap:10}}>
                <Tag variant={s.variant} dot><Icon name={s.icon} size={11} style={{marginRight:2}}/>{s.label}</Tag>
                <span className="text-xs fg-muted">{groups[s.key].length} khách</span>
                <div style={{flex:1,height:1,background:'var(--border-1)'}}/>
              </div>
              <div className="grid grid-2">
                {groups[s.key].map(c => (
                  <div key={c.id} className="pipeline-card" onClick={() => onOpenCustomer(c)} style={{margin:0}}>
                    <div className="row gap-3" style={{alignItems:'flex-start'}}>
                      <Avatar name={c.name} tier={tierVariant(c.tier)}/>
                      <div style={{flex:1,minWidth:0}}>
                        <div className="row gap-2">
                          <div className="strong fg-1">{c.name}</div>
                          <Tag variant={tierVariant(c.tier)}>{c.tier}</Tag>
                        </div>
                        <div className="text-xs fg-muted mt-1 tnum">{c.phone} · LTV {fmt.vndFull(c.ltv)}</div>
                        <div className="text-sm fg-2 mt-2" style={{lineHeight:1.5}}>
                          <Icon name="flag" size={12} style={{display:'inline-block',marginRight:4,color:'var(--vs-light-blue)'}}/>
                          {c.followUp.reason}
                        </div>
                        <div className="row mt-3 gap-1" onClick={(e) => e.stopPropagation()}>
                          {isTelesale && (
                            <button className="btn btn-cta btn-sm" onClick={() => onGoToTelesale && onGoToTelesale(c)}>
                              <Icon name="phone" size={12}/>Gọi ngay
                            </button>
                          )}
                          {isInstore && (
                            <button className="btn btn-cta btn-sm" onClick={() => onLogOrder && onLogOrder(c)}>
                              <Icon name="receipt" size={12}/>Ghi nhận đơn
                            </button>
                          )}
                          <button className="btn btn-secondary btn-sm">
                            <Icon name="clock" size={12}/>Hoãn
                          </button>
                          <button className="btn btn-ghost btn-sm">
                            <Icon name="check" size={12}/>Đã xong
                          </button>
                          <span style={{flex:1}}/>
                          <span className="text-xs fg-muted">{c.preferredContact}</span>
                        </div>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}

// ===== Customer Pipeline (Kanban) =====
// Cột pipeline (kanban) — dữ liệu thật từ /api/pipeline, kéo-thả để đổi trạng thái.
const PIPELINE_COLS = [
  {key:'lead',      label:'Lead mới',        desc:'Khách vừa thêm, chưa liên hệ', color:'var(--fg-muted)'},
  {key:'contacted', label:'Đã liên hệ',      desc:'Đã gọi/nhắn, đang tư vấn',    color:'var(--vs-light-blue)'},
  {key:'nurturing', label:'Đang nuôi dưỡng', desc:'Quan tâm, chờ quyết định',   color:'#f59e0b'},
  {key:'won',       label:'Đã chốt ✅',       desc:'Đã mua/ký hợp đồng',          color:'var(--status-success)', endpoint:true},
  {key:'paused',    label:'Tạm dừng',        desc:'Chưa có nhu cầu / nguy cơ rời', color:'var(--status-sale)', endpoint:true},
];
// won và paused cùng cấp (3) — chỉ đến được từ nurturing, không thể chuyển giữa chúng
const STAGE_ORDER_FE = { lead: 0, contacted: 1, nurturing: 2, won: 3, paused: 3, done: 4, lost: 3 };
function CustomerPipeline({ refreshKey, myName, onOpenCustomer, kind, role }) {
  kind = kind || 'customer';
  const isAdmin = role && role.role === 'admin';
  const [entries, setEntries] = useState(null);
  const [dragId, setDragId] = useState(null);
  const [dragCustomerId, setDragCustomerId] = useState(null);
  const [overCol, setOverCol] = useState(null);
  const [confirmMove, setConfirmMove] = useState(null); // { id, fromStage, toStage, entryName }
  const [showDone, setShowDone] = useState(false);
  const live = window.TVS_API && window.TVS_API.isAuthed();

  const [candidateList, setCandidateList] = useState([]);

  const load = () => {
    if (!live) { setEntries([]); return; }
    window.TVS_API.api('/api/pipeline?kind=' + kind).then(r => setEntries(r.entries || [])).catch(() => setEntries([]));
  };
  useEffect(() => { load(); }, [kind, refreshKey]);

  const [showAddModal, setShowAddModal] = useState(false);
  const [searchQ, setSearchQ] = useState('');
  const [searchPicks, setSearchPicks] = useState([]);
  const [searchTotal, setSearchTotal] = useState(0);
  const [modalSelected, setModalSelected] = useState(new Set());
  const [addingSelected, setAddingSelected] = useState(false);

  useEffect(() => {
    if (!showAddModal || !live) return;
    const q = searchQ.trim();
    // Gộp khách lẻ + đối tác: tìm trong TẤT CẢ khách thuộc phân quyền (không lọc theo nhóm).
    // Không gõ gì -> danh sách khách cập nhật gần đây; gõ tên/SĐT -> tìm toàn bộ.
    const url = '/api/customers/list?pageSize=50' + (q.length >= 1 ? '&q=' + encodeURIComponent(q) : '&sort=recent');
    const t = setTimeout(() => {
      window.TVS_API.api(url)
        .then(r => { setSearchPicks(r.customers || []); setSearchTotal(r.total || 0); })
        .catch(() => { setSearchPicks([]); setSearchTotal(0); });
    }, q.length === 0 ? 0 : 250);
    return () => clearTimeout(t);
  }, [searchQ, showAddModal, kind, live]);

  // Bỏ khách đã có trong pipeline khỏi danh sách chọn (đỡ thêm trùng).
  const pipelineIdSet = useMemo(() => new Set((entries || []).map(e => e.customer && e.customer.id).filter(Boolean)), [entries]);
  const modalPicks = searchPicks.filter(c => !pipelineIdSet.has(c.id));

  const addSelectedToPipeline = async () => {
    if (modalSelected.size === 0) return;
    setAddingSelected(true);
    try {
      for (const cid of modalSelected) {
        await window.TVS_API.api('/api/pipeline', {
          method: 'POST',
          body: JSON.stringify({ customerId: cid, kind, stage: 'lead' })
        });
      }
      window.tvsToast && window.tvsToast(`Đã thêm ${modalSelected.size} mục vào pipeline`);
      setShowAddModal(false);
      setModalSelected(new Set());
      setSearchQ('');
      load();
    } catch (e) {
      window.tvsToast && window.tvsToast('Lỗi: ' + e.message);
    }
    setAddingSelected(false);
  };

  const tryMove = (id, toStage) => {
    const entry = entries.find(e => e.id === id);
    if (!entry) return;
    if (entry.stage === toStage) return;
    const fromOrder = STAGE_ORDER_FE[entry.stage] ?? 0;
    const toOrder   = STAGE_ORDER_FE[toStage] ?? 0;
    // Chặn đi ngược
    if (toOrder < fromOrder) {
      window.tvsToast && window.tvsToast('⛔ Quy trình 1 chiều — không thể quay lại bước trước');
      return;
    }
    // Chặn chuyển ngang giữa 2 bước cùng cấp (won ↔ paused)
    if (toOrder === fromOrder && entry.stage !== toStage) {
      window.tvsToast && window.tvsToast('⛔ Đã chốt và Tạm dừng là 2 hướng kết thúc riêng biệt — không thể chuyển giữa chúng');
      return;
    }
    // Tiến về phía trước — yêu cầu xác nhận
    setConfirmMove({ id, fromStage: entry.stage, toStage, entryName: entry.customer?.name || 'khách hàng' });
  };
  const doMove = async (id, stage) => {
    setEntries(list => list.map(e => e.id === id ? { ...e, stage } : e));
    try {
      const r = await window.TVS_API.api('/api/pipeline/' + id, { method:'PATCH', body: JSON.stringify({ stage }) });
      // Cập nhật note từ server (có vết log)
      if (r.entry && r.entry.note !== undefined) {
        setEntries(list => list.map(e => e.id === id ? { ...e, note: r.entry.note } : e));
      }
    } catch (e) {
      const msg = e?.message || '';
      if (msg.includes('1 chiều')) {
        window.tvsToast && window.tvsToast('⛔ Không thể quay lại bước trước');
      } else {
        window.tvsToast && window.tvsToast('Lỗi: ' + msg);
      }
      load();
    }
  };
  const remove = async (id) => {
    if (!isAdmin) {
      window.tvsToast && window.tvsToast('Chỉ admin mới có thể xóa khỏi pipeline');
      return;
    }
    setEntries(list => list.filter(e => e.id !== id));
    try { await window.TVS_API.api('/api/pipeline/' + id, { method:'DELETE' }); } catch (e) { load(); }
  };

  const addToPipelineFromDraggable = async (customerId, stage) => {
    const tempId = 'temp-' + Date.now();
    const targetCust = kind === 'partner' ? D.partners.find(p => p.id === customerId) : D.customers.find(c => c.id === customerId);
    if (!targetCust) return;
    
    const newEntry = {
      id: tempId,
      stage,
      customer: {
        id: targetCust.id,
        name: targetCust.name,
        phone: targetCust.phone,
        tier: targetCust.tier,
        ltv: targetCust.ltv || targetCust.gmvYTD || 0,
      },
      mine: true,
      owner: (role && role.person) || 'Nhân viên'
    };
    
    setEntries(list => [...list, newEntry]);
    
    try {
      const r = await window.TVS_API.api('/api/pipeline', {
        method: 'POST',
        body: JSON.stringify({ customerId, stage })
      });
      setEntries(list => list.map(e => e.id === tempId ? r.entry : e));
    } catch (e) {
      window.tvsToast && window.tvsToast('Lỗi: ' + e.message);
      load();
    }
  };

  const candidates = useMemo(() => {
    if (entries === null) return [];
    const inPipeline = new Set(entries.map(e => e.customer?.id).filter(Boolean));
    const now = Date.now();
    const sevenDaysAgo = now - 7 * 864e5;
    
    if (!live) {
      if (kind === 'partner') {
        return D.partners.filter(p => {
          if (inPipeline.has(p.id)) return false;
          const isNew = p.onboarded ? new Date(p.onboarded).getTime() >= sevenDaysAgo : true;
          const hasFollowUp = !!p.nextAction;
          return isNew || hasFollowUp;
        }).slice(0, 12);
      } else {
        return D.customers.filter(c => {
          if (inPipeline.has(c.id)) return false;
          const isNew = c.joined ? new Date(c.joined).getTime() >= sevenDaysAgo : false;
          const hasFollowUp = !!c.followUpId || !!c.followUp;
          return isNew || hasFollowUp;
        }).slice(0, 12);
      }
    }

    // Gộp: tệp nhanh gồm mọi khách (lẻ + đối tác) mới/có follow-up/CRM, không lọc theo nhóm.
    return candidateList.filter(c => {
      if (inPipeline.has(c.id)) return false;
      const isNew = c.joined ? new Date(c.joined).getTime() >= sevenDaysAgo : true;
      const hasFollowUp = !!c.followUpId || !!c.followUp;
      const isCrm = c._source === 'crm' || c.source === 'crm';
      return isNew || hasFollowUp || isCrm;
    }).slice(0, 12);
  }, [entries, kind, candidateList, live]);

  if (entries === null) return <Card><div className="text-sm fg-muted">Đang tải pipeline…</div></Card>;
  const activeEntries = entries.filter(e => e.stage !== 'done');

  const title = kind === 'partner'
    ? (myName ? 'Pipeline đối tác của tôi' : 'Pipeline đối tác — toàn hệ thống')
    : (myName ? 'Pipeline khách hàng của tôi' : 'Pipeline khách hàng — toàn hệ thống');

  return (
    <Card pad={false}>
      <CardHeader title={title}
        sub="Kéo-thả thẻ giữa các cột để cập nhật trạng thái. Chỉ bạn thấy pipeline của mình; quản lý cửa hàng/admin thấy toàn bộ."
        actions={
          <button className="btn btn-cta btn-sm" onClick={() => setShowAddModal(true)}>
            <Icon name="plus" size={12}/>{kind === 'partner' ? 'Chọn đối tác B2B' : 'Chọn khách hàng'}
          </button>
        }
      />
      {candidates.length > 0 && (
        <div style={{padding:'var(--space-3) var(--space-5)', background:'var(--bg-soft)', borderBottom:'1px solid var(--border-1)', display:'flex', flexDirection:'column', gap:8}}>
          <div className="strong fg-2 text-xs" style={{textTransform:'uppercase', letterSpacing:'0.05em'}}>Tệp nhanh (mới trong 7 ngày hoặc có follow-up) — kéo vào cột để thêm vào Pipeline:</div>
          <div className="row gap-2" style={{flexWrap:'wrap'}}>
            {candidates.map(c => (
              <div key={c.id} draggable
                onDragStart={() => setDragCustomerId(c.id)}
                onDragEnd={() => setDragCustomerId(null)}
                onClick={() => addToPipelineFromDraggable(c.id, 'lead')}
                className="btn btn-secondary btn-sm"
                style={{cursor:'grab', display:'inline-flex', alignItems:'center', gap:6, padding:'4px 10px', background:'var(--bg-page)', border:'1px solid var(--border-2)', borderRadius:'var(--radius-sm)'}}>
                <Icon name={kind === 'partner' ? 'handshake' : 'user'} size={12} style={{color:'var(--vs-light-blue)'}}/>
                <span className="strong">{c.name}</span>
                <span className="text-xs fg-muted tnum">({c.phone})</span>
                <span style={{fontSize:10, color:'var(--vs-light-blue)'}}>+ Thêm</span>
              </div>
            ))}
          </div>
        </div>
      )}
      {activeEntries.length === 0 ? (
        <div className="card-pad" style={{
          textAlign: 'center', padding: 'var(--space-6) var(--space-4)', color: 'var(--fg-muted)',
          background: 'var(--bg-soft)', borderRadius: '0 0 var(--radius-lg) var(--radius-lg)'
        }}>
          <div style={{
            width: 56, height: 56, borderRadius: '50%', background: 'var(--bg-page)',
            display: 'flex', alignItems: 'center', justifySelf: 'center', justifyContent: 'center',
            marginBottom: 16, border: '1px solid var(--border-1)', color: 'var(--vs-light-blue)'
          }}>
            <Icon name="target" size={24}/>
          </div>
          <div className="text-sm strong fg-1 mb-1">Hiện đang không có pipeline nào trong tiến trình</div>
          <div className="text-xs fg-muted mb-4" style={{maxWidth: 320, margin: '0 auto 16px'}}>
            Quy trình trống. Hãy thêm đối tác/khách hàng vào pipeline để bắt đầu theo dõi tiến độ chăm sóc.
          </div>
          <button className="btn btn-secondary btn-sm" onClick={() => setShowAddModal(true)} style={{display: 'inline-flex', alignItems: 'center', gap: 6, margin: '0 auto'}}>
            <Icon name="plus" size={12}/> {kind === 'partner' ? 'Chọn đối tác B2B' : 'Chọn khách hàng'}
          </button>
        </div>
      ) : (
        <div className="card-pad">
          {/* Flow diagram — visual quy trình */}
          <div className="row" style={{gap:4, marginBottom:14, alignItems:'center', background:'var(--bg-soft)', borderRadius:'var(--radius-sm)', padding:'8px 14px', fontSize:11, color:'var(--fg-muted)', border:'1px solid var(--border-1)', flexWrap:'wrap'}}>
            <Icon name="warning" size={12} style={{color:'var(--vs-light-blue)', marginRight:4, flexShrink:0}}/>
            <span style={{fontWeight:700, color:'var(--fg-2)'}}>Quy trình 1 chiều:</span>
            {['Lead mới','Đã liên hệ','Đang nuôi dưỡng'].map((s, i) => (
              <span key={s} className="row" style={{alignItems:'center', gap:4}}>
                <span style={{padding:'2px 8px', borderRadius:4, background:'var(--bg-page)', border:'1px solid var(--border-2)', fontWeight:500}}>{s}</span>
                <span style={{color:'var(--vs-light-blue)', fontWeight:800, fontSize:14}}>→</span>
              </span>
            ))}
            <span className="row" style={{alignItems:'center', gap:4}}>
              <span style={{padding:'2px 8px', borderRadius:4, background:'rgba(0,180,80,0.1)', border:'1px solid rgba(0,180,80,0.3)', fontWeight:600, color:'var(--status-success)'}}>Đã chốt ✅</span>
              <span style={{color:'var(--fg-muted)', fontWeight:700, fontSize:12}}>HOẶC</span>
              <span style={{padding:'2px 8px', borderRadius:4, background:'rgba(220,60,60,0.08)', border:'1px solid rgba(220,60,60,0.25)', fontWeight:600, color:'var(--status-sale)'}}>Tạm dừng ⏸</span>
            </span>
            <span style={{padding:'2px 8px', borderRadius:4, background:'rgba(0,150,255,0.08)', border:'1px solid rgba(0,150,255,0.25)', fontWeight:600, color:'var(--vs-light-blue)', marginLeft:4}}>→ Kết thúc 📋</span>
            <span style={{marginLeft:'auto', color:'var(--status-sale)', fontSize:10, flexShrink:0}}>⛔ Không thể quay lại</span>
          </div>

          {/* Kanban 3 cols (active) + 2 endpoint cols */}
          <div style={{display:'grid', gridTemplateColumns:'repeat(3,1fr) 2fr', gap:'var(--space-3)'}}>
            {/* 3 cột active */}
            {PIPELINE_COLS.filter(c => !c.endpoint).map((col, colIdx) => {
              const items = entries.filter(e => e.stage === col.key);
              return (
                <div key={col.key} className="pipeline-col"
                  onDragOver={(ev) => { ev.preventDefault(); setOverCol(col.key); }}
                  onDragLeave={() => setOverCol(null)}
                  onDrop={() => {
                    if (dragId) tryMove(dragId, col.key);
                    else if (dragCustomerId) addToPipelineFromDraggable(dragCustomerId, col.key);
                    setDragId(null); setDragCustomerId(null); setOverCol(null);
                  }}
                  style={overCol===col.key?{outline:'2px dashed var(--vs-light-blue)',outlineOffset:2,borderRadius:'var(--radius-sm)'}:undefined}>
                  <h4 style={{display:'flex',alignItems:'center',justifyContent:'space-between'}}>
                    <span style={{display:'flex',alignItems:'center',gap:5}}>
                      {colIdx > 0 && <span style={{color:'var(--vs-light-blue)',fontSize:16,fontWeight:800}}>→</span>}
                      <span style={{color: col.color||'var(--fg-1)'}}>{col.label}</span>
                    </span>
                    <span className="count">{items.length}</span>
                  </h4>
                  <div className="text-xs fg-muted mb-3">{col.desc}</div>
                  {items.map(e => (
                    <div key={e.id} className="pipeline-card" draggable
                      onDragStart={() => setDragId(e.id)} onDragEnd={() => setDragId(null)}
                      onClick={() => e.customer && onOpenCustomer && onOpenCustomer(D.customers.find(c=>c.id===e.customer.id)||{id:e.customer.id,name:e.customer.name,phone:e.customer.phone,tier:e.customer.tier,ltv:e.customer.ltv,tags:[],code:e.customer.code,orders:0,avgOrder:0})}>
                      <div className="row gap-2 mb-2">
                        <Avatar name={e.customer?e.customer.name:'?'} size="sm" tier={tierVariant(e.customer&&e.customer.tier)}/>
                        <div style={{flex:1,minWidth:0}}>
                          <div className="name">{e.customer?e.customer.name:'(đối tác)'}</div>
                          <div className="meta tnum">{e.customer?e.customer.phone:''}</div>
                        </div>
                        {!myName && !e.mine && <Tag variant="outline" style={{fontSize:9}}>{e.owner || ''}</Tag>}
                      </div>
                      {e.note && <div className="text-xs fg-muted mt-2" style={{whiteSpace:'pre-line',background:'var(--bg-soft)',padding:'4px 8px',borderRadius:'var(--radius-sm)',borderLeft:'2px solid var(--vs-light-blue)',maxHeight:72,overflow:'auto'}}>{e.note}</div>}
                      <div className="row" style={{justifyContent:'space-between',alignItems:'center',marginTop:6}}>
                        <div className="value" style={{margin:0}}>{e.customer&&e.customer.ltv>0?fmt.vndFull(e.customer.ltv):''}</div>
                        <div className="row gap-1">
                          <button className="btn btn-icon btn-sm btn-ghost" title="Ghi chú" onClick={(ev) => {
                            ev.stopPropagation();
                            const userNote = prompt("Nhập ghi chú cho pipeline này:");
                            if (userNote !== null) {
                              const nowStr = new Date().toLocaleString('vi-VN', { day:'2-digit', month:'2-digit', year:'numeric', hour:'2-digit', minute:'2-digit' });
                              const newNote = (e.note || '') + (e.note ? '\n' : '') + `💬 [Ghi chú ${nowStr}]: ${userNote}`;
                              window.TVS_API.api('/api/pipeline/' + e.id, { method: 'PATCH', body: JSON.stringify({ note: newNote }) })
                                .then(load)
                                .catch(() => {});
                            }
                          }}>
                            <Icon name="note" size={11}/>
                          </button>
                          {isAdmin && (e.mine||myName===null) && (
                            <button className="btn btn-icon btn-sm btn-ghost" title="Gỡ (admin)" onClick={(ev)=>{ev.stopPropagation();remove(e.id);}}><Icon name="close" size={11}/></button>
                          )}
                        </div>
                      </div>
                    </div>
                  ))}
                  {items.length === 0 && <div style={{textAlign:'center',padding:'var(--space-4) var(--space-2)',color:'var(--fg-muted)',fontSize:11}}>Kéo thẻ vào đây</div>}
                </div>
              );
            })}

            {/* Cột đôi: Đã chốt + Tạm dừng (ngang hàng, endpoint) */}
            <div style={{display:'flex',flexDirection:'column',gap:'var(--space-3)'}}>
              {PIPELINE_COLS.filter(c => c.endpoint).map(col => {
                const items = entries.filter(e => e.stage === col.key);
                const isWon = col.key === 'won';
                const accentColor = isWon ? 'rgba(0,180,80,0.18)' : 'rgba(220,60,60,0.10)';
                const borderColor = isWon ? 'rgba(0,180,80,0.35)' : 'rgba(220,60,60,0.28)';
                return (
                  <div key={col.key} className="pipeline-col"
                    onDragOver={(ev) => { ev.preventDefault(); setOverCol(col.key); }}
                    onDragLeave={() => setOverCol(null)}
                    onDrop={() => {
                      if (dragId) tryMove(dragId, col.key);
                      else if (dragCustomerId) addToPipelineFromDraggable(dragCustomerId, col.key);
                      setDragId(null); setDragCustomerId(null); setOverCol(null);
                    }}
                    style={{...( overCol===col.key ? {outline:'2px dashed var(--vs-light-blue)',outlineOffset:2} : {}), background:accentColor, border:`1px solid ${borderColor}`, borderRadius:'var(--radius-md)', flex:1, padding:'var(--space-3)'}}>
                    <h4 style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:4}}>
                      <span style={{display:'flex',alignItems:'center',gap:5}}>
                        <span style={{color:'var(--vs-light-blue)',fontSize:16,fontWeight:800}}>→</span>
                        <span style={{color:col.color}}>{col.label}</span>
                      </span>
                      <span className="count">{items.length}</span>
                    </h4>
                    <div className="text-xs fg-muted mb-2">{col.desc} · <span style={{fontStyle:'italic'}}>Cuối</span></div>
                    {/* Cảnh báo tự kết thúc */}
                    <div style={{fontSize:10,color:'var(--fg-muted)',background:'var(--bg-soft)',padding:'4px 8px',borderRadius:4,marginBottom:8,border:'1px solid var(--border-1)'}}>
                      ⏰ Tự động lưu lịch sử sau <strong>7 ngày</strong> nếu không có hành động
                    </div>
                    {items.map(e => (
                      <div key={e.id} className="pipeline-card" draggable
                        onDragStart={()=>setDragId(e.id)} onDragEnd={()=>setDragId(null)}
                        onClick={()=>e.customer&&onOpenCustomer&&onOpenCustomer(D.customers.find(c=>c.id===e.customer.id)||{id:e.customer.id,name:e.customer.name,phone:e.customer.phone,tier:e.customer.tier,ltv:e.customer.ltv,tags:[],code:e.customer.code,orders:0,avgOrder:0})}
                        style={{cursor:'pointer'}}>
                        <div className="row gap-2">
                          <Avatar name={e.customer?e.customer.name:'?'} size="sm" tier={tierVariant(e.customer&&e.customer.tier)}/>
                          <div style={{flex:1,minWidth:0}}>
                            <div className="name">{e.customer?e.customer.name:'(đối tác)'}</div>
                            <div className="meta tnum">{e.customer?e.customer.phone:''}</div>
                          </div>
                          {!myName && !e.mine && <Tag variant="outline" style={{fontSize:9}}>{e.owner || ''}</Tag>}
                        </div>
                        {e.note && <div className="text-xs fg-muted mt-2" style={{whiteSpace:'pre-line',background:'var(--bg-soft)',padding:'4px 8px',borderRadius:'var(--radius-sm)',borderLeft:`2px solid ${col.color}`,maxHeight:60,overflow:'auto'}}>{e.note}</div>}
                        <div className="row" style={{justifyContent:'space-between',alignItems:'center',marginTop:6}}>
                          <div className="value" style={{margin:0,fontSize:11}}>{e.customer&&e.customer.ltv>0?fmt.vndFull(e.customer.ltv):''}</div>
                          <div className="row gap-1">
                            <button className="btn btn-icon btn-sm btn-ghost" title="Ghi chú" onClick={(ev) => {
                              ev.stopPropagation();
                              const userNote = prompt("Nhập ghi chú cho pipeline này:");
                              if (userNote !== null) {
                                const nowStr = new Date().toLocaleString('vi-VN', { day:'2-digit', month:'2-digit', year:'numeric', hour:'2-digit', minute:'2-digit' });
                                const newNote = (e.note || '') + (e.note ? '\n' : '') + `💬 [Ghi chú ${nowStr}]: ${userNote}`;
                                window.TVS_API.api('/api/pipeline/' + e.id, { method: 'PATCH', body: JSON.stringify({ note: newNote }) })
                                  .then(load)
                                  .catch(() => {});
                              }
                            }}>
                              <Icon name="note" size={11}/>
                            </button>
                            {isAdmin && <button className="btn btn-icon btn-sm btn-ghost" title="Gỡ (admin)" onClick={(ev)=>{ev.stopPropagation();remove(e.id);}}><Icon name="close" size={10}/></button>}
                          </div>
                        </div>
                        {/* Nút kết thúc — nổi bật */}
                        <button
                          style={{
                            marginTop:8, width:'100%', padding:'7px 0', fontSize:12, fontWeight:700,
                            background: isWon ? 'rgba(0,160,80,0.85)' : 'rgba(180,50,50,0.75)',
                            color:'#fff', border:'none', borderRadius:'var(--radius-sm)',
                            cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', gap:5,
                            boxShadow:'0 1px 4px rgba(0,0,0,0.18)',
                            transition:'opacity 0.15s',
                          }}
                          onMouseEnter={e2 => e2.currentTarget.style.opacity='0.82'}
                          onMouseLeave={e2 => e2.currentTarget.style.opacity='1'}
                          onClick={async (ev) => {
                            ev.stopPropagation();
                            if (isWon) {
                              const rawCodes = prompt("Nhập các mã đơn hàng Sapo liên kết (có thể nhập nhiều mã cách nhau bằng dấu phẩy hoặc khoảng trắng):");
                              if (rawCodes === null) return; // User cancelled
                              const codes = rawCodes.split(/[\s,;]+/).map(s => s.trim().toUpperCase()).filter(Boolean);
                              if (codes.length === 0) {
                                window.tvsToast && window.tvsToast('❌ Bắt buộc nhập mã đơn Sapo để kết thúc và tính doanh số!');
                                return;
                              }
                              setEntries(list => list.filter(e2 => e2.id !== e.id));
                              try {
                                await window.TVS_API.api('/api/pipeline/' + e.id, { 
                                  method:'PATCH', 
                                  body: JSON.stringify({ stage: 'done', orderCodes: codes.join(', ') }) 
                                });
                                window.tvsToast && window.tvsToast('📋 Đã kết thúc và lưu lịch sử doanh số!');
                              } catch(err) { load(); }
                            } else {
                              if (!window.confirm('Kết thúc pipeline cho ' + (e.customer?.name||'khách hàng') + '?\nCard sẽ được lưu vào Lịch sử pipeline.')) return;
                              setEntries(list => list.filter(e2 => e2.id !== e.id));
                              try {
                                await window.TVS_API.api('/api/pipeline/' + e.id, { method:'PATCH', body: JSON.stringify({ stage: 'done' }) });
                                window.tvsToast && window.tvsToast('📋 Đã lưu vào lịch sử pipeline');
                              } catch(err) { load(); }
                            }
                          }}
                        >
                          <Icon name="check" size={12}/> Kết thúc · Lưu lịch sử
                        </button>
                      </div>
                    ))}
                    {items.length === 0 && <div style={{textAlign:'center',padding:'var(--space-3)',color:'var(--fg-muted)',fontSize:11}}>Kéo thẻ vào đây</div>}
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      )}

      {/* ===== LỊCH SỬ PIPELINE ===== */}
      {entries.some(e => e.stage === 'done') && (
        <div style={{borderTop:'2px solid var(--border-1)'}}>
          <button
            onClick={() => setShowDone(d => !d)}
            style={{width:'100%', textAlign:'left', background:'none', border:'none', padding:'14px 20px', cursor:'pointer', display:'flex', alignItems:'center', gap:10, color:'var(--fg-2)'}}
          >
            <div style={{width:32,height:32,borderRadius:8,background:'rgba(0,150,255,0.1)',display:'flex',alignItems:'center',justifyContent:'center'}}>
              <Icon name={showDone ? 'chevron-down' : 'chevron-right'} size={14} style={{color:'var(--vs-light-blue)'}}/>
            </div>
            <div>
              <div className="strong fg-1" style={{fontSize:14}}>📋 Lịch sử Pipeline</div>
              <div className="text-xs fg-muted">{entries.filter(e=>e.stage==='done').length} pipeline đã kết thúc · Bấm để xem</div>
            </div>
          </button>
          {showDone && (
            <div style={{padding:'0 20px 20px'}}>
              <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(260px,1fr))',gap:10}}>
                {entries.filter(e => e.stage === 'done').map(e => (
                  <div key={e.id} className="pipeline-card" style={{border:'1px solid rgba(0,150,255,0.2)',background:'rgba(0,150,255,0.04)',opacity:0.9}}>
                    <div className="row gap-2">
                      <Avatar name={e.customer?e.customer.name:'?'} size="sm"/>
                      <div style={{flex:1,minWidth:0}}>
                        <div className="name">{e.customer?e.customer.name:'(đối tác)'}</div>
                        <div className="meta tnum">{e.customer?e.customer.phone:''}</div>
                      </div>
                      <Tag variant="info" dot>Kết thúc</Tag>
                    </div>
                    {!myName && e.owner && <div className="text-xs fg-muted mt-1">Sales: {e.owner}</div>}
                    {e.note && (
                      <div className="text-xs fg-muted mt-2" style={{whiteSpace:'pre-line',background:'var(--bg-soft)',padding:'4px 8px',borderRadius:4,borderLeft:'2px solid var(--vs-light-blue)',maxHeight:80,overflow:'auto'}}>
                        {e.note}
                      </div>
                    )}
                    {e.customer && e.customer.ltv > 0 && (
                      <div className="value mt-2" style={{fontSize:12,margin:0}}>{fmt.vndFull(e.customer.ltv)}</div>
                    )}
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}

      {/* Confirmation dialog */}
      {confirmMove && (
        <div style={{position:'fixed',inset:0,background:'rgba(1,33,105,0.5)',zIndex:500,display:'flex',justifyContent:'center',alignItems:'center',padding:16}}>
          <div className="card" style={{background:'var(--bg-page)',width:'min(420px,94vw)',borderRadius:'var(--radius-lg)',boxShadow:'var(--shadow-pop)',padding:24}}>
            <div className="row gap-3 mb-4">
              <div style={{width:40,height:40,borderRadius:'50%',background:'rgba(255,180,0,0.15)',display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0}}>
                <Icon name="warning" size={20} style={{color:'#f59e0b'}}/>
              </div>
              <div>
                <div className="strong fg-1" style={{fontSize:16}}>Xác nhận chuyển bước</div>
                <div className="text-sm fg-muted mt-1">Quy trình pipeline chỉ đi 1 chiều. Hãy kiểm tra kỹ trước khi tiến!</div>
              </div>
            </div>

            <div style={{background:'var(--bg-soft)',borderRadius:'var(--radius-sm)',padding:'12px 16px',marginBottom:16}}>
              <div className="text-sm fg-2 mb-2">Chuyển <b>{confirmMove.entryName}</b>:</div>
              <div className="row gap-2" style={{alignItems:'center'}}>
                <Tag variant="outline">{PIPELINE_COLS.find(c => c.key === confirmMove.fromStage)?.label || confirmMove.fromStage}</Tag>
                <span style={{color:'var(--vs-light-blue)',fontWeight:800,fontSize:18}}>→</span>
                <Tag variant="info">{PIPELINE_COLS.find(c => c.key === confirmMove.toStage)?.label || confirmMove.toStage}</Tag>
              </div>
              <div className="text-xs fg-muted mt-3" style={{color:'var(--status-sale)'}}>⛔ Sau khi xác nhận, không thể quay lại bước trước</div>
            </div>

            <div className="row gap-2" style={{justifyContent:'flex-end'}}>
              <button className="btn btn-secondary btn-sm" onClick={() => setConfirmMove(null)}>Hủy — kiểm tra lại</button>
              <button style={{
                padding:'6px 14px', fontSize:13, fontWeight:700, borderRadius:'var(--radius-sm)',
                background:'var(--vs-dark-blue)', color:'#fff', border:'none', cursor:'pointer'
              }} onClick={() => {
                doMove(confirmMove.id, confirmMove.toStage);
                setConfirmMove(null);
              }}>
                ✓ Xác nhận chuyển bước
              </button>
            </div>
          </div>
        </div>
      )}

      {showAddModal && (
        <div style={{position:'fixed',inset:0,background:'rgba(1,33,105,0.40)',zIndex:400,display:'flex',justifyContent:'center',alignItems:'center',padding:16}}>
          <div className="card" style={{background:'var(--bg-page)',width:'min(500px,94vw)',maxHeight:'80vh',borderRadius:'var(--radius-lg)',boxShadow:'var(--shadow-pop)',display:'flex',flexDirection:'column'}}>
            <div style={{padding:'var(--space-4) var(--space-5)',borderBottom:'1px solid var(--border-1)',display:'flex',justifyContent:'space-between',alignItems:'center'}}>
              <h3 style={{margin:0,fontSize:'var(--t-md)',color:'var(--fg-1)'}}>{kind === 'partner' ? 'Chọn đối tác vào Pipeline' : 'Chọn khách hàng vào Pipeline'}</h3>
              <button className="btn btn-icon btn-ghost btn-sm" onClick={() => setShowAddModal(false)}><Icon name="close" size={16}/></button>
            </div>
            
            <div style={{padding:'var(--space-4) var(--space-5)',flex:1,overflow:'auto'}}>
              <input className="input mb-2" placeholder={kind === 'partner' ? "Tìm đối tác theo tên/SĐT..." : "Tìm khách hàng theo tên/SĐT — trong toàn bộ khách của bạn"}
                value={searchQ} onChange={e=>setSearchQ(e.target.value)} autoFocus />

              <div className="text-xs fg-muted mb-2" style={{lineHeight:1.5}}>
                {searchQ.trim()
                  ? <>Kết quả tìm kiếm: <b>{modalPicks.length}</b> khách khớp.</>
                  : <>Đang hiện <b>{modalPicks.length}</b> khách cập nhật gần đây (chưa có trong pipeline). Gõ tên/SĐT để tìm trong <b>{searchTotal.toLocaleString('vi-VN')}</b> khách thuộc phân quyền của bạn.</>}
              </div>

              <div style={{maxHeight:300,overflow:'auto',border:'1px solid var(--border-1)',borderRadius:'var(--radius-md)'}}>
                {modalPicks.length === 0 ? (
                  <div style={{padding:20,textAlign:'center',color:'var(--fg-muted)',fontSize:13}}>{searchQ.trim() ? 'Không tìm thấy kết quả' : 'Tất cả khách gần đây đã ở trong pipeline — gõ để tìm thêm'}</div>
                ) : (
                  modalPicks.map(c => {
                    const isSelected = modalSelected.has(c.id);
                    return (
                      <label key={c.id} style={{display:'flex',alignItems:'center',gap:12,padding:'10px 12px',borderBottom:'1px solid var(--border-1)',cursor:'pointer',userSelect:'none',background:isSelected?'var(--bg-soft)':'none'}}>
                        <input type="checkbox" checked={isSelected}
                          style={{accentColor:'var(--vs-light-blue)', width:16, height:16}}
                          onChange={(e) => {
                            const newSel = new Set(modalSelected);
                            if (e.target.checked) newSel.add(c.id);
                            else newSel.delete(c.id);
                            setModalSelected(newSel);
                          }}/>
                        <div style={{flex:1,minWidth:0}}>
                          <div className="text-sm strong fg-1">{c.name}</div>
                          <div className="text-xs fg-muted tnum">{c.phone} · {c.code}</div>
                        </div>
                      </label>
                    );
                  })
                )}
              </div>
            </div>
            
            <div style={{padding:'var(--space-3) var(--space-5)',borderTop:'1px solid var(--border-1)',display:'flex',justifyContent:'flex-end',gap:8,background:'var(--bg-soft)'}}>
              <button className="btn btn-secondary btn-sm" onClick={() => setShowAddModal(false)}>Hủy</button>
              <button className="btn btn-cta btn-sm" disabled={addingSelected || modalSelected.size === 0} onClick={addSelectedToPipeline}>
                {addingSelected ? 'Đang thêm...' : `Thêm ${modalSelected.size} mục`}
              </button>
            </div>
          </div>
        </div>
      )}
    </Card>
  );
}

// ===========================================================
// Customer 360 — drawer
// ===========================================================
function Customer360({ customer: rawCust, onClose, onCall, onLogOrder, role }) {
  const customer = useMemo(() => {
    if (!rawCust) return {};
    const name = rawCust.name || rawCust.fullName || 'Khách mới';
    const code = rawCust.code || ('KH-' + rawCust.id.slice(0, 6));
    const joined = rawCust.joined || (rawCust.createdAt ? new Date(rawCust.createdAt).toISOString().slice(0, 10) : null);
    const gender = rawCust.gender === 'male' ? 'Nam' : rawCust.gender === 'female' ? 'Nữ' : (rawCust.gender || 'Khác');
    const age = rawCust.age || (rawCust.birthYear ? new Date().getFullYear() - rawCust.birthYear : null);
    const channel = rawCust.channel || (rawCust.acquisitionChannel === 'wholesale' ? 'Wholesale' : 'Cửa hàng');

    return {
      id: rawCust.id,
      code,
      name,
      phone: rawCust.phone || '',
      email: rawCust.email || '',
      tier: rawCust.tier || 'Bronze',
      joined,
      gender,
      age,
      city: rawCust.city || '',
      ltv: rawCust.ltv || rawCust.ltvCached || 0,
      orders: rawCust.orders || rawCust.ordersCountCached || 0,
      avgOrder: rawCust.avgOrder || (rawCust.ordersCountCached ? Math.round((rawCust.ltvCached || 0) / rawCust.ordersCountCached) : 0),
      lastOrder: rawCust.lastOrder || rawCust.lastOrderAt,
      tags: rawCust.tags || [],
      note: rawCust.note || '',
      nps: rawCust.nps || null,
      channel,
      consent: rawCust.consent || { sms: true, email: true, zalo: true, call: true },
      preferredContact: rawCust.preferredContact || 'Gọi điện',
      followUp: rawCust.followUp || null,
      followUpId: rawCust.followUpId || null,
      _ownerId: rawCust._ownerId || rawCust.ownerUserId || null,
      _owner: rawCust._owner || '',
      _collaboratorIds: rawCust._collaboratorIds || rawCust.collaboratorIds || null,
    };
  }, [rawCust]);

  const live = !!(window.TVS_API && window.TVS_API.isAuthed());
  const [tab, setTab] = useState('overview');
  const [showMakePartner, setShowMakePartner] = useState(false);
  const isPartner = !!(rawCust && (rawCust._isPartner || rawCust.partnerType));
  // Lịch sử đơn: mẫu 300 có sẵn trong D.ordersByCustomer; khách mở ngoài mẫu -> fetch thật.
  const baseOrders = D.ordersByCustomer[customer.id] || [];
  const [fetchedOrders, setFetchedOrders] = useState(null);
  useEffect(() => {
    setFetchedOrders(null);
    if (baseOrders.length === 0 && window.TVS_API && window.TVS_API.isAuthed()) {
      window.TVS_API.api('/api/customers/' + customer.id + '/orders-history')
        .then(r => setFetchedOrders(r.orders || [])).catch(() => setFetchedOrders([]));
    }
  }, [customer.id]);
  const orders = baseOrders.length ? baseOrders : (fetchedOrders || []);
  const ordersLoading = baseOrders.length === 0 && fetchedOrders === null;
  const isInstore  = role && role.id === 'instore';
  const isTelesale = role && role.id === 'telesale';
  // Phụ trách (assign) — chỉ admin đổi được người chăm sóc khách này.
  const canAssign = role && role.role === 'admin';
  // Người phụ trách — hỗ trợ NHIỀU người (checkbox).
  const parseOwnerIds = (c) => c._collaboratorIds
    ? String(c._collaboratorIds).split(',').map(s => s.trim()).filter(Boolean)
    : (c._ownerId ? [c._ownerId] : []);
  const [ownerIds, setOwnerIds] = useState(parseOwnerIds(customer));
  const [assignees, setAssignees] = useState([]);
  useEffect(() => { setOwnerIds(parseOwnerIds(customer)); }, [customer.id]);
  useEffect(() => { if (canAssign) window.TVS_API && window.TVS_API.assignable().then(r => setAssignees(r.users || [])).catch(() => {}); }, [canAssign]);
  const ownerDisplay = (ownerIds.length && assignees.length)
    ? assignees.filter(u => ownerIds.includes(u.id)).map(u => u.name).join(' + ')
    : (customer._owner || '');
  const changeOwners = async (ids) => {
    const list = (ids || []).filter(Boolean);
    const prev = ownerIds;
    setOwnerIds(list);
    try {
      await window.TVS_API.api('/api/customers/' + customer.id + '/owner', { method: 'PATCH', body: JSON.stringify({ ownerUserIds: list }) });
      window.tvsToast && window.tvsToast('Đã cập nhật người phụ trách');
    } catch (e) { setOwnerIds(prev); window.tvsToast && window.tvsToast('Lỗi: ' + e.message); }
  };
  const session = useTvsSession();
  const sessionNotes     = session.notesByCustomer[customer.id]     || [];
  const sessionFollowUps = session.followupsByCustomer[customer.id] || [];

  const [activity, setActivity] = useState(null);
  const [activityLoading, setActivityLoading] = useState(false);
  const fetchActivity = () => {
    if (window.TVS_API && window.TVS_API.isAuthed() && customer.id) {
      setActivityLoading(true);
      window.TVS_API.api('/api/customers/' + customer.id + '/activity')
        .then(r => { setActivity(r); setActivityLoading(false); })
        .catch(() => { setActivity({ notes: [], followUps: [] }); setActivityLoading(false); });
    }
  };
  useEffect(() => {
    setActivity(null);
    fetchActivity();
  }, [customer.id]);

  const [noteTag, setNoteTag] = useState('note');

  const notesList = activity ? activity.notes.map(n => ({
    id: n.id,
    who: n.author || 'Nhân viên',
    role: 'Kinh doanh',
    when: fmt.rel(n.at),
    text: n.body,
    tag: n.tag,
    _real: true
  })) : [];

  const latestNote = notesList[0] || (sessionNotes[0] ? {
    text: sessionNotes[0].text,
    tag: sessionNotes[0].tag,
    who: sessionNotes[0].who,
    role: sessionNotes[0].role,
    when: sessionNotes[0].when
  } : null);

  const followUpsList = activity ? (activity.followUps || []).map(f => ({
    id: f.id,
    reason: f.reason || '',
    status: f.status || 'pending',
    channel: f.channel || '',
    dueAt: f.dueAt,
    doneAt: f.doneAt,
    assignedTo: f.assignedTo || '',
    _real: true
  })) : [];

  const latestFollowUp = followUpsList.find(f => f.status === 'pending') || (sessionFollowUps[0] ? {
    reason: sessionFollowUps[0].reason,
    dueAt: sessionFollowUps[0].dueAt,
    channel: sessionFollowUps[0].channel,
    assignedTo: sessionFollowUps[0].who,
  } : null);

  // 12 months of monthly spend (real)
  const monthly = useMemo(() => {
    const buckets = Array.from({ length: 12 }, () => 0);
    const now = new Date();
    const base = now.getFullYear() * 12 + now.getMonth();
    
    if (orders.length === 0) {
      if (live) return Array.from({length: 12}, () => 0);
      const seed = customer.id.charCodeAt(2);
      return Array.from({length: 12}, (_, i) => {
        const v = ((seed * (i+1) * 37) % 9) / 10 + 0.3;
        return Math.round(v * (customer.avgOrder/1000 || 500) * (1 + i/12));
      });
    }

    orders.forEach(o => {
      if (!o.date) return;
      const d = new Date(o.date);
      const idx = 11 - (base - (d.getFullYear() * 12 + d.getMonth()));
      if (idx >= 0 && idx < 12) {
        buckets[idx] += (o.total || 0);
      }
    });
    return buckets.map(v => Math.round(v / 1000));
  }, [orders, customer.id, customer.avgOrder]);

  // Suggested products based on tags
  const suggestions = useMemo(() => {
    const tags = (customer.tags || []).map(t => t.toLowerCase());
    if (tags.length === 0) return [];
    return D.products.filter(p => {
      const name = p.name.toLowerCase();
      return tags.some(t => name.includes(t.replace(/\s.*/, '').toLowerCase()) || (t.includes('whey') && name.includes('whey')));
    }).slice(0,4);
  }, [customer]);

  return (
    <>
    <div className="drawer-overlay" onClick={onClose}>
      <div className="drawer" onClick={(e) => e.stopPropagation()}>
        <div className="drawer-h">
          <Avatar name={customer.name} size="lg" tier={tierVariant(customer.tier)}/>
          <div style={{flex:1}}>
            <div className="row gap-3">
              <h2 style={{color:'#fff',margin:0,fontFamily:'var(--font-display)',fontSize:24,fontWeight:700}}>{customer.name}</h2>
              <Tag variant={tierVariant(customer.tier)}>{customer.tier}</Tag>
            </div>
            <div className="row gap-4 mt-2" style={{color:'rgba(255,255,255,0.78)',fontSize:13}}>
              <span>📞 <span className="tnum">{customer.phone}</span></span>
              <span>✉ {customer.email}</span>
              <span>📍 {customer.city}</span>
              <span>🎂 {customer.gender}, {customer.age}</span>
            </div>
            <div className="row gap-2 mt-2" style={{alignItems:'center'}}>
              <span style={{color:'rgba(255,255,255,0.6)',fontSize:12}}>Phụ trách:</span>
              {canAssign ? (
                <OwnerPicker currentIds={ownerIds} assignees={assignees} onChange={changeOwners} dark fallbackLabel={ownerDisplay || ''}/>
              ) : (
                <span style={{color:'#fff',fontSize:12,fontWeight:600}}>{ownerDisplay || 'Chưa có người phụ trách'}</span>
              )}
            </div>
          </div>
          <button className="btn btn-cta" onClick={isInstore ? () => onLogOrder && onLogOrder(customer) : onCall}>
            <Icon name={isInstore ? 'receipt' : 'phone'} size={14}/>{isInstore ? 'Ghi nhận đơn' : 'Gọi ngay'}
          </button>
          {!isInstore && (
            <button className="btn btn-secondary" style={{background:'rgba(255,255,255,0.10)',color:'#fff',borderColor:'transparent'}} onClick={() => onLogOrder && onLogOrder(customer)}>
              <Icon name="receipt" size={14}/>Ghi nhận đơn
            </button>
          )}
          <button className="btn btn-secondary" style={{background:'rgba(255,255,255,0.10)',color:'#fff',borderColor:'transparent'}}>
            <Icon name="chat" size={14}/>Zalo
          </button>
          {live && (isPartner ? (
            <span className="tag info" style={{alignSelf:'center'}}>Đối tác</span>
          ) : (
            <button className="btn btn-secondary" style={{background:'rgba(255,255,255,0.10)',color:'#fff',borderColor:'transparent'}} title="Chuyển khách này thành đối tác B2B" onClick={() => setShowMakePartner(true)}>
              <Icon name="handshake" size={14}/>Chuyển thành đối tác
            </button>
          ))}
          <button className="close" onClick={onClose}>
            <Icon name="close" size={18}/>
          </button>
        </div>

        {/* Hero stats strip */}
        <div style={{display:'grid',gridTemplateColumns:'repeat(5,1fr)',padding:'var(--space-5) var(--space-6)',borderBottom:'1px solid var(--border-1)',background:'var(--bg-soft)'}}>
          {[
            {l:'LTV', v:fmt.vndFull(customer.ltv), dim:'12 tháng'},
            {l:'Tổng đơn', v:customer.orders, dim:'+3 quý này'},
            {l:'Giá trị TB', v:fmt.vndFull(customer.avgOrder)},
            {l:'NPS', v:customer.nps ?? '—', dim: customer.nps >= 9 ? 'Promoter' : customer.nps >= 7 ? 'Passive' : customer.nps ? 'Detractor' : 'Chưa khảo sát'},
            {l:'Khách từ', v:fmt.date(customer.joined).slice(3), dim: 'qua kênh ' + customer.channel},
          ].map((s,i) => (
            <div key={i}>
              <div style={{fontSize:10,letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--fg-muted)',fontWeight:700,marginBottom:4}}>{s.l}</div>
              <div style={{fontFamily:'var(--font-display)',fontWeight:700,fontSize:20,color:'var(--fg-1)',lineHeight:1}}>{s.v}</div>
              {s.dim && <div className="text-xs fg-muted mt-2">{s.dim}</div>}
            </div>
          ))}
        </div>

        {/* Tabs */}
        <div className="tabs" style={{padding:'0 var(--space-6)'}}>
          {[
            ['overview','Tổng quan'],
            ['orders','Đơn hàng'],
            ['activity','Hoạt động'],
            ['notes','Ghi chú & Follow-up'],
          ].map(([k,l]) => (
            <button key={k} className={`tab ${tab===k?'active':''}`} onClick={()=>setTab(k)}>{l}</button>
          ))}
        </div>

        <div style={{padding:'var(--space-5) var(--space-6)'}}>
          {tab === 'overview' && (
            <>
              {customer.followUp && (
                <div className="banner mb-4">
                  <Icon name="flag" size={18}/>
                  <div style={{flex:1}}>
                    <div className="bold">Follow-up: {customer.followUp.reason}</div>
                    <div className="text-xs fg-muted">Hạn: {fmt.rel(customer.followUp.due)} · Kênh ưa thích: {customer.preferredContact}</div>
                  </div>
                  <button className="btn btn-cta btn-sm">Xử lý ngay</button>
                </div>
              )}

              {latestFollowUp && (
                <div className="banner mb-4" style={{background:'rgba(65,182,230,0.10)',borderColor:'rgba(65,182,230,0.40)'}}>
                  <Icon name="clock" size={18}/>
                  <div style={{flex:1}}>
                    <div className="bold">Follow-up: {latestFollowUp.reason}</div>
                    <div className="text-xs fg-muted">
                      Hẹn: {latestFollowUp._real ? fmt.date(latestFollowUp.dueAt) : fmt.date(latestFollowUp.date)} {latestFollowUp.time || ''} 
                      · Kênh: {latestFollowUp.channel || '—'} 
                      · Bởi: {latestFollowUp.assignedTo || latestFollowUp.who || 'AM'}
                    </div>
                  </div>
                  <Tag variant="info" dot>{latestFollowUp.status === 'pending' ? 'Chưa xử lý' : 'Mới'}</Tag>
                </div>
              )}

              <div className="grid grid-7-5">
                <Card>
                  <div className="row mb-4">
                    <h3 style={{margin:0,fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Doanh số 12 tháng qua</h3>
                    <span className="text-xs fg-muted" style={{marginLeft:'auto'}}>Tổng: {fmt.vndFull(monthly.reduce((a,b)=>a+b*1000,0))}</span>
                  </div>
                  <BarChart data={monthly} height={140} highlight={11}/>
                  <div className="row mt-3" style={{justifyContent:'space-between',fontSize:11,color:'var(--fg-muted)'}}>
                    <span>T6</span><span>T7</span><span>T8</span><span>T9</span><span>T10</span><span>T11</span><span>T12</span><span>T1</span><span>T2</span><span>T3</span><span>T4</span><span>T5</span>
                  </div>
                </Card>

                <Card>
                  <h3 style={{margin:'0 0 var(--space-4)',fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Liên hệ & Đồng ý</h3>
                  <div className="col gap-3">
                    {[
                      ['Gọi điện','call'],['SMS','sms'],['Email','email'],['Zalo','zalo'],
                    ].map(([l,k]) => (
                      <div key={k} className="row">
                        <span className="text-sm fg-2" style={{flex:1}}>{l}</span>
                        <Tag variant={customer.consent[k] ? 'success' : 'danger'}>
                          {customer.consent[k] ? 'Đã đồng ý' : 'Từ chối'}
                        </Tag>
                      </div>
                    ))}
                    <div className="divider mt-2"/>
                    <div className="row">
                      <span className="text-sm fg-2" style={{flex:1}}>Kênh ưa thích</span>
                      <span className="bold" style={{color:'var(--fg-1)'}}>{customer.preferredContact}</span>
                    </div>
                  </div>
                </Card>
              </div>

              <Card className="mt-4">
                <div className="row mb-4">
                  <h3 style={{margin:0,fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Gợi ý sản phẩm cross-sell</h3>
                  <Tag variant="info" style={{marginLeft:'auto'}}>AI suggested</Tag>
                </div>
                <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:12}}>
                  {suggestions.length > 0 ? suggestions.map(p => (
                    <div key={p.sku} className="prod-tile">
                      <div className="ph"><Icon name="pill" size={28}/></div>
                      <div className="name">{p.name}</div>
                      <div className="row">
                        <span className="price">{fmt.vndFull(p.price)}</span>
                        <button className="btn btn-icon btn-cta btn-sm" style={{marginLeft:'auto'}}><Icon name="plus" size={12}/></button>
                      </div>
                    </div>
                  )) : <div className="empty" style={{gridColumn:'span 4'}}>Chưa có gợi ý</div>}
                </div>
              </Card>

              <div className="grid grid-2 mt-4">
                <Card>
                  <h3 style={{margin:'0 0 var(--space-4)',fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Tags & Phân khúc</h3>
                  <div className="row gap-2" style={{flexWrap:'wrap'}}>
                    {customer.tags.map(t => (
                      <Tag key={t} variant={t === 'At-risk' ? 'danger' : t === 'New' ? 'info' : 'outline'}>{t}</Tag>
                    ))}
                    <button className="btn btn-ghost btn-sm"><Icon name="plus" size={12}/>Thêm tag</button>
                  </div>
                </Card>
                <Card>
                  <h3 style={{margin:'0 0 var(--space-4)',fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Ghi chú gần nhất</h3>
                  {latestNote ? (
                    <>
                      {latestNote.tag && latestNote.tag !== 'general' && (
                        <Tag variant={latestNote.tag==='complaint'?'danger':latestNote.tag==='feedback'?'success':latestNote.tag==='opportunity'?'warning':'info'} style={{marginBottom:8}}>
                          {({preference:'Sở thích',feedback:'Phản hồi',complaint:'Khiếu nại',opportunity:'Cơ hội bán'})[latestNote.tag]}
                        </Tag>
                      )}
                      <div className="text-sm fg-2" style={{lineHeight:1.6,whiteSpace:'pre-wrap'}}>{latestNote.text}</div>
                      <div className="text-xs fg-muted mt-3">{latestNote.who} · {latestNote.role} · {latestNote.when}</div>
                    </>
                  ) : (
                    <>
                      <div className="text-sm fg-2" style={{lineHeight:1.6}}>{customer.note || 'Chưa có ghi chú nào.'}</div>
                      {customer.note && !live && <div className="text-xs fg-muted mt-3">Nguyễn Mỹ Linh · 3 ngày trước</div>}
                      {customer.note && live && <div className="text-xs fg-muted mt-3">Từ CRM</div>}
                    </>
                  )}
                </Card>
              </div>
            </>
          )}

          {tab === 'orders' && (
            <Card pad={false}>
              <CardHeader title={`${orders.length} đơn hàng`} sub="Nguồn gốc: Sapo · đơn ghi nhận tay tự đối soát trong 15 phút"/>
              <div className="table-wrap">
                <table className="tbl">
                  <thead>
                    <tr>
                      <th>Mã đơn</th><th>Ngày</th><th>Kênh</th><th className="num">SP</th><th className="num">Tổng</th><th>Trạng thái</th><th>Đối soát Sapo</th>
                    </tr>
                  </thead>
                  <tbody>
                    {((session.ordersByCustomer && session.ordersByCustomer[customer.id]) || []).map(o => (
                      <tr key={o.id}>
                        <td className="strong tnum">{o.ref || o.id}</td>
                        <td className="text-sm">{o.date ? fmt.date(o.date) : 'Hôm nay'}</td>
                        <td><Tag variant="outline">{o.channel === 'store' ? 'Cửa hàng' : o.channel === 'telesale' ? 'Telesale' : o.channel || 'CRM'}</Tag></td>
                        <td className="num tnum">{o.items}</td>
                        <td className="num strong">{fmt.vndFull(o.total)}</td>
                        <td><Tag variant="info" dot>Ghi nhận tay</Tag></td>
                        <td><Tag variant="warning" dot>Chờ khớp</Tag></td>
                      </tr>
                    ))}
                    {orders.map((o) => (
                      <tr key={o.id}>
                        <td className="strong tnum">{o.id}</td>
                        <td className="text-sm">{o.date ? fmt.date(o.date) : '—'}</td>
                        <td><Tag variant="outline">{o.channel}</Tag></td>
                        <td className="num tnum">{o.items}</td>
                        <td className="num strong">{fmt.vndFull(o.total)}</td>
                        <td><Tag variant="success" dot>{o.status}</Tag></td>
                        <td><Tag variant="success" dot>Khớp Sapo</Tag></td>
                      </tr>
                    ))}
                    {ordersLoading && <tr><td colSpan={7}><div className="text-sm fg-muted" style={{padding:'var(--space-3)'}}>Đang tải lịch sử đơn…</div></td></tr>}
                    {!ordersLoading && orders.length === 0 && ((session.ordersByCustomer && session.ordersByCustomer[customer.id]) || []).length === 0 && (
                      <tr><td colSpan={7}><div className="text-sm fg-muted" style={{padding:'var(--space-3)'}}>Chưa có đơn hàng nào.</div></td></tr>
                    )}
                  </tbody>
                </table>
              </div>
            </Card>
          )}

          {tab === 'activity' && (
            <Card>
              <h3 style={{margin:'0 0 var(--space-4)',fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Dòng thời gian</h3>
              {(() => {
                const timelineList = [];
                if (activity) {
                  activity.notes.forEach(n => {
                    timelineList.push({
                      ico: n.tag === 'call' ? 'phone' : 'note',
                      title: `${n.tag === 'call' ? 'Ghi chú cuộc gọi' : 'Ghi chú'} — ${n.author || 'Nhân viên'}`,
                      meta: `${fmt.rel(n.at)} · ${n.body}`,
                      color: n.tag === 'call' ? 'success' : 'info',
                      at: new Date(n.at)
                    });
                  });
                }
                orders.forEach(o => {
                  timelineList.push({
                    ico: 'cart',
                    title: `Đặt đơn ${o.id}`,
                    meta: `${o.date ? fmt.date(o.date) : 'Hôm nay'} · ${o.channel} · ${fmt.vndFull(o.total)}`,
                    color: 'success',
                    at: o.date ? new Date(o.date) : new Date()
                  });
                });
                timelineList.sort((a, b) => b.at - a.at);

                const finalTimeline = timelineList.length > 0 ? timelineList : (live ? [] : [
                  {ico:'cart',title:'Đặt đơn DH-2026-0428-3391',meta:'7 ngày trước · App · 2.389.000đ',color:'success'},
                  {ico:'mail',title:'Mở email "Combo giảm 20% — Whey vị mới"',meta:'8 ngày trước · Tỷ lệ mở 64%',color:'info'},
                  {ico:'phone',title:'Cuộc gọi tư vấn — Mỹ Linh',meta:'12 ngày trước · 4:21 · Chốt đơn',color:'success'},
                  {ico:'chat',title:'Phản hồi Zalo — hỏi về Collagen',meta:'18 ngày trước',color:'info'},
                  {ico:'star',title:'Đánh giá 5★ — Whey Protein',meta:'22 ngày trước',color:'warning'},
                  {ico:'cart',title:'Đặt đơn DH-2026-0411-2877',meta:'24 ngày trước · App · 689.000đ',color:'success'},
                ]);

                if (finalTimeline.length === 0) {
                  return <div className="text-sm fg-muted" style={{padding:'20px 0',textAlign:'center'}}>Chưa có hoạt động nào được ghi nhận.</div>;
                }

                return finalTimeline.map((a,i) => (
                  <div key={i} className="activity">
                    <div className="ico"><Icon name={a.ico} size={14}/></div>
                    <div className="body">
                      <div className="title">{a.title}</div>
                      <div className="meta">{a.meta}</div>
                    </div>
                  </div>
                ));
              })()}
            </Card>
          )}

          {tab === 'notes' && (
            <>
              {/* Database & Session follow-ups (newest first) */}
              {(followUpsList.length > 0 || sessionFollowUps.length > 0) && (
                <Card pad={false} className="mb-4">
                  <CardHeader title="Lịch follow-up" sub={`${followUpsList.length + sessionFollowUps.length} lịch cần theo dõi`}/>
                  <div className="card-pad">
                    {followUpsList.map(f => (
                      <div key={f.id} className="activity" style={{display:'flex', alignItems:'center', justifyContent:'space-between', padding:'8px 0'}}>
                        <div style={{display:'flex', gap:12, alignItems:'center'}}>
                          <div className="ico" style={{color: f.status === 'done' ? 'var(--status-success)' : 'var(--vs-light-blue)'}}><Icon name={f.status === 'done' ? 'check' : 'clock'} size={14}/></div>
                          <div className="body">
                            <div className="title" style={{textDecoration: f.status === 'done' ? 'line-through' : 'none', color: f.status === 'done' ? 'var(--fg-muted)' : 'var(--fg-1)', fontWeight: 600}}>{f.reason}</div>
                            <div className="text-xs fg-muted">Hẹn: {fmt.date(f.dueAt)} · Kênh: {f.channel || '—'} · Người nhận: {f.assignedTo || 'AM'}</div>
                          </div>
                        </div>
                        <div className="row gap-2" onClick={(e) => e.stopPropagation()}>
                          <Tag variant={f.status === 'done' ? 'success' : 'info'} dot>{f.status === 'done' ? 'Đã xong' : 'Chưa xử lý'}</Tag>
                          {f.status === 'pending' && (
                            <button className="btn btn-secondary btn-sm" title="Hoàn tất" onClick={async () => {
                              if (window.TVS_API && window.TVS_API.isAuthed()) {
                                try {
                                  await window.TVS_API.api('/api/followups/' + f.id + '/done', { method:'PATCH', body:'{}' });
                                  fetchActivity();
                                } catch (e) {
                                  window.tvsToast && window.tvsToast('Lỗi cập nhật: ' + e.message);
                                }
                              }
                            }}>
                              Xong
                            </button>
                          )}
                        </div>
                      </div>
                    ))}
                    {sessionFollowUps.map(f => (
                      <div key={f.id} className="activity">
                        <div className="ico" style={{color:'var(--vs-light-blue)'}}><Icon name="clock" size={14}/></div>
                        <div className="body">
                          <div className="title">{f.reason}</div>
                          <div className="meta">Hẹn: {fmt.date(f.date)} {f.time} · Kênh {f.channel} · {f.who} · {f.createdAt}</div>
                        </div>
                        <Tag variant="info" dot>Đã đặt</Tag>
                      </div>
                    ))}
                  </div>
                </Card>
              )}

              <Card className="mb-4">
                <h3 style={{margin:'0 0 var(--space-4)',fontSize:'var(--t-md)',color:'var(--fg-1)'}}>Thêm ghi chú mới</h3>
                <textarea className="textarea" placeholder="VD: Khách quan tâm Whey vị mới, sẽ quyết định cuối tuần..." id="qa-quick-note"/>
                <div className="row mt-3">
                  <Segmented value={noteTag} options={[
                    {value:'note',label:'Ghi chú'},
                    {value:'call',label:'Cuộc gọi'},
                    {value:'task',label:'Tạo task'},
                  ]} onChange={setNoteTag}/>
                  <button className="btn btn-cta" style={{marginLeft:'auto'}}
                    onClick={async () => {
                      const el = document.getElementById('qa-quick-note');
                      const v = el && el.value.trim();
                      if (!v) return;
                      const tag = noteTag === 'call' ? 'call' : noteTag === 'task' ? 'task' : 'general';
                      if (window.TVS_API && window.TVS_API.isAuthed()) {
                        try {
                          await window.TVS_API.addNote(customer.id, { body: v, tag });
                          fetchActivity();
                        } catch (e) {
                          window.tvsToast && window.tvsToast('Lỗi: ' + e.message);
                        }
                      } else {
                        const meName = (role && role.person) || 'Nguyễn Mỹ Linh';
                        const meRole = (role && role.team) || 'Kinh doanh';
                        window.TVS_SESSION.addNote(customer.id, { text: v, tag, who: meName, role: meRole });
                      }
                      if (el) el.value = '';
                    }}>Lưu ghi chú</button>
                </div>
              </Card>
              <Card pad={false}>
                <CardHeader title="Ghi chú trước đây" sub={`${notesList.length + (live ? 0 : 3)} mục`}/>
                <div className="card-pad">
                  {live && notesList.length === 0 ? (
                    <div className="text-sm fg-muted" style={{padding:'16px 0',textAlign:'center'}}>Chưa có ghi chú nào.</div>
                  ) : (live ? notesList : [
                    ...notesList,
                    {who:'Nguyễn Mỹ Linh', role:'Telesale', when:'3 ngày trước', text: customer.note || 'Chưa có ghi chú đầu tiên.'},
                    {who:'Trần Quốc Bảo', role:'Cửa hàng Q.1', when:'12 ngày trước', text:'Khách ghé cửa hàng, mua thêm Magnesium. Tư vấn đổi sang gói Family combo.'},
                    {who:'Lê Hà Phương', role:'CS', when:'1 tháng trước', text:'Khách phản hồi tốt về Whey vị mới. Đề xuất add vào câu chuyện thành công cho marketing.'},
                  ]).map((n,i) => (
                    <div key={n.id || i} className="activity">
                      <Avatar name={n.who} size="sm"/>
                      <div className="body">
                        <div className="row gap-2">
                          <div className="title">{n.who} <span className="text-xs fg-muted">· {n.role} · {n.when}</span></div>
                          {n._real && <Tag variant="info">Mới</Tag>}
                          {n.tag && n.tag !== 'general' && (
                            <Tag variant={n.tag==='complaint'?'danger':n.tag==='feedback'?'success':n.tag==='opportunity'?'warning':n.tag==='call'?'success':'info'}>
                              {({preference:'Sở thích',feedback:'Phản hồi',complaint:'Khiếu nại',opportunity:'Cơ hội bán',call:'Cuộc gọi',task:'Task'})[n.tag] || n.tag}
                            </Tag>
                          )}
                        </div>
                        <div className="text-sm fg-2 mt-2" style={{whiteSpace:'pre-wrap'}}>{n.text}</div>
                      </div>
                    </div>
                  ))}
                </div>
              </Card>
            </>
          )}
        </div>
      </div>
    </div>
    {showMakePartner && (
      <MakePartnerModal
        customerId={customer.id}
        customerName={customer.name}
        onClose={() => setShowMakePartner(false)}
        onDone={async () => {
          setShowMakePartner(false);
          if (window.TVS_API && window.TVS_API.isAuthed()) {
            try { await window.TVS_API.refresh(); } catch (_) {}
            window.tvsRefreshUI && window.tvsRefreshUI();
          }
          onClose && onClose();
        }}/>
    )}
    </>
  );
}

// Modal chọn loại đối tác khi chuyển khách thường → đối tác B2B.
function MakePartnerModal({ customerId, customerName, onClose, onDone }) {
  const TYPES = [
    { k:'wholesale',        l:'Đại lý / Phân phối' },
    { k:'tiktok_affiliate', l:'TikTok Affiliate / KOC' },
    { k:'pharmacy',         l:'Nhà thuốc' },
    { k:'gym',              l:'Phòng gym' },
    { k:'pt',               l:'PT / HLV' },
    { k:'spa',              l:'Spa & Nutritionist' },
    { k:'enterprise',       l:'Doanh nghiệp' },
  ];
  const [type, setType] = useState('wholesale');
  const [commission, setCommission] = useState('');
  const [busy, setBusy] = useState(false);
  const submit = async () => {
    setBusy(true);
    try {
      await window.TVS_API.api('/api/customers/' + customerId + '/make-partner', {
        method: 'POST', body: JSON.stringify({ type, commission: commission || undefined }),
      });
      window.tvsToast && window.tvsToast(`Đã chuyển ${customerName || 'khách'} thành đối tác`);
      onDone && onDone();
    } catch (e) {
      window.tvsToast && window.tvsToast('Lỗi: ' + e.message);
      setBusy(false);
    }
  };
  return (
    <div className="drawer-overlay" style={{justifyContent:'center',alignItems:'center'}} onClick={(e)=>{ e.stopPropagation(); onClose(); }}>
      <div onClick={(e) => e.stopPropagation()}
        style={{background:'var(--bg-page)',width:'min(440px, 95vw)',borderRadius:'var(--radius-lg)',overflow:'hidden',boxShadow:'var(--shadow-pop)',animation:'slidein 0.28s var(--ease-out)'}}>
        <div style={{padding:'var(--space-5) var(--space-6)',background:'var(--vs-dark-blue)',color:'#fff'}}>
          <div className="row">
            <div style={{flex:1}}>
              <div className="eyebrow" style={{color:'var(--vs-light-blue)'}}>Chuyển thành đối tác B2B</div>
              <h2 style={{margin:'4px 0 0',fontFamily:'var(--font-display)',fontSize:20,fontWeight:700,color:'#fff'}}>{customerName}</h2>
            </div>
            <button onClick={onClose} style={{background:'rgba(255,255,255,0.18)',border:'none',color:'#fff',width:36,height:36,borderRadius:'50%',cursor:'pointer',display:'inline-flex',alignItems:'center',justifyContent:'center'}}>
              <Icon name="close" size={16}/>
            </button>
          </div>
        </div>
        <div style={{padding:'var(--space-5) var(--space-6)'}}>
          <div className="field-label">Loại đối tác</div>
          <select className="select mb-3" value={type} onChange={(e)=>setType(e.target.value)}>
            {TYPES.map(t => <option key={t.k} value={t.k}>{t.l}</option>)}
          </select>
          <div className="field-label">% Hoa hồng (tuỳ chọn)</div>
          <input className="input tnum" type="number" min="0" max="100" placeholder="VD: 10" value={commission} onChange={(e)=>setCommission(e.target.value)}/>
          <div className="text-xs fg-muted mt-3" style={{lineHeight:1.5}}>Khách sẽ được gắn nhãn <b>Đối tác</b>, mở thêm tab Hoa hồng & Hợp đồng. Có thể tinh chỉnh sau trong hồ sơ đối tác.</div>
        </div>
        <div style={{padding:'var(--space-4) var(--space-6)',background:'var(--bg-soft)',borderTop:'1px solid var(--border-1)',display:'flex',gap:'var(--space-3)',justifyContent:'flex-end'}}>
          <button className="btn btn-ghost" onClick={onClose}>Hủy</button>
          <button className="btn btn-cta" disabled={busy} onClick={submit}>{busy ? 'Đang chuyển…' : <><Icon name="handshake" size={14}/>Chuyển thành đối tác</>}</button>
        </div>
      </div>
    </div>
  );
}

window.CustomersScreen = CustomersScreen;
window.Customer360 = Customer360;
window.MakePartnerModal = MakePartnerModal;
window.ownerOf = ownerOf;
window.CustomerPipeline = CustomerPipeline;

// ===========================================================
// QuickActionModal — Ghi chú nhanh / Đặt lịch follow-up
// (popup nhỏ giữa màn hình, không cần mở drawer 360°)
// ===========================================================
function QuickActionModal({ mode, customer, role, onClose }) {
  const isNote = mode === 'note';
  const isTelesale = role && role.id === 'telesale';

  const [text, setText] = useState('');
  const [reason, setReason] = useState('');
  const [date, setDate] = useState(isTelesale ? '2026-05-16' : '2026-05-17');
  const [time, setTime] = useState('10:00');
  const [channel, setChannel] = useState(customer.preferredContact || 'Gọi điện');
  const [tag, setTag] = useState('general');
  const [saved, setSaved] = useState(false);

  const handleSave = () => {
    const meName = role && role.id === 'instore' ? 'Trần Quốc Bảo' : 'Nguyễn Mỹ Linh';
    const meRole = (role && role.team) || 'Kinh doanh';
    if (isNote) {
      window.TVS_SESSION.addNote(customer.id, { text, tag, who: meName, role: meRole });
    } else {
      window.TVS_SESSION.addFollowUp(customer.id, { reason, date, time, channel, who: meName, role: meRole });
    }
    setSaved(true);
    setTimeout(onClose, 1100);
  };

  return (
    <div className="drawer-overlay" style={{justifyContent:'center',alignItems:'center'}} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()}
        style={{background:'var(--bg-page)',width:'min(560px, 94vw)',maxHeight:'90vh',display:'flex',flexDirection:'column',borderRadius:'var(--radius-lg)',overflow:'hidden',boxShadow:'var(--shadow-pop)',animation:'slidein 0.28s var(--ease-out)'}}>

        {/* Header */}
        <div style={{padding:'var(--space-4) var(--space-5)',background:isNote ? 'var(--vs-dark-blue)' : 'var(--vs-light-blue)',color:'#fff',display:'flex',gap:'var(--space-3)',alignItems:'center'}}>
          <div style={{width:40,height:40,borderRadius:'50%',background:'rgba(255,255,255,0.18)',display:'flex',alignItems:'center',justifyContent:'center',color:'#fff'}}>
            <Icon name={isNote ? 'note' : 'clock'} size={20}/>
          </div>
          <div style={{flex:1}}>
            <div style={{fontSize:11,letterSpacing:'0.14em',textTransform:'uppercase',color:'rgba(255,255,255,0.7)',fontWeight:700}}>
              {isNote ? 'Ghi chú nhanh' : 'Đặt lịch follow-up'}
            </div>
            <h3 style={{margin:'2px 0 0',fontFamily:'var(--font-display)',fontSize:18,fontWeight:700,color: isNote ? '#fff' : 'var(--vs-dark-blue)'}}>{customer.name}</h3>
          </div>
          <button onClick={onClose}
            style={{background:'rgba(255,255,255,0.18)',border:'none',color:'#fff',width:32,height:32,borderRadius:'50%',cursor:'pointer',display:'inline-flex',alignItems:'center',justifyContent:'center'}}>
            <Icon name="close" size={14}/>
          </button>
        </div>

        {/* Body */}
        {saved ? (
          <div style={{padding:'var(--space-8) var(--space-6)',textAlign:'center'}}>
            <div style={{width:56,height:56,borderRadius:'50%',background:'var(--status-success)',color:'#fff',display:'inline-flex',alignItems:'center',justifyContent:'center',marginBottom:'var(--space-3)'}}>
              <Icon name="check" size={28} stroke={3}/>
            </div>
            <div className="strong fg-1" style={{fontSize:16,marginBottom:4}}>
              {isNote ? 'Đã lưu ghi chú' : 'Đã đặt lịch follow-up'}
            </div>
            <div className="text-sm fg-muted">
              {isNote ? 'Ghi chú đã được gắn vào hồ sơ khách hàng.' : `Hệ thống sẽ nhắc bạn ngày ${fmt.date(date)} lúc ${time}.`}
            </div>
          </div>
        ) : (
          <>
            <div style={{padding:'var(--space-4) var(--space-5)'}}>
              {/* Customer mini-card */}
              <div className="row gap-3 mb-4" style={{padding:'10px 12px',background:'var(--bg-soft)',borderRadius:'var(--radius-md)'}}>
                <Avatar name={customer.name} size="sm" tier={tierVariant(customer.tier)}/>
                <div style={{flex:1,minWidth:0}}>
                  <div className="row gap-2">
                    <div className="strong fg-1">{customer.name}</div>
                    <Tag variant={tierVariant(customer.tier)}>{customer.tier}</Tag>
                  </div>
                  <div className="text-xs fg-muted tnum">{customer.phone} · {customer.id}</div>
                </div>
              </div>

              {isNote ? (
                <>
                  <div className="field-label">Loại ghi chú</div>
                  <div className="row gap-1 mb-3" style={{flexWrap:'wrap'}}>
                    {[
                      {k:'general',  l:'Chung',         c:'outline'},
                      {k:'preference',l:'Sở thích',    c:'info'},
                      {k:'feedback', l:'Phản hồi',     c:'success'},
                      {k:'complaint',l:'Khiếu nại',    c:'danger'},
                      {k:'opportunity',l:'Cơ hội bán', c:'warning'},
                    ].map(t => (
                      <button key={t.k}
                        className={tag===t.k ? 'btn btn-cta btn-sm' : 'btn btn-secondary btn-sm'}
                        onClick={() => setTag(t.k)}>
                        {t.l}
                      </button>
                    ))}
                  </div>
                  <div className="field-label">Nội dung</div>
                  <textarea className="textarea" autoFocus
                    placeholder="VD: Khách quan tâm Whey vị mới, sẽ quyết định cuối tuần. Đã hỏi giá combo gym tăng cơ..."
                    value={text} onChange={(e)=>setText(e.target.value)}
                    style={{minHeight:120,fontSize:14,lineHeight:1.5}}/>
                  <div className="row mt-3" style={{gap:8,flexWrap:'wrap'}}>
                    <span className="text-xs fg-muted">Gợi ý nhanh:</span>
                    {['Khách chốt đơn, đợi giao', 'Cần gọi lại tuần sau', 'Quan tâm sản phẩm mới', 'Đã giới thiệu chương trình VIP'].map(s => (
                      <button key={s} className="btn btn-ghost btn-sm" style={{fontSize:11,padding:'2px 8px'}}
                        onClick={() => setText(text ? text + '\n' + s : s)}>
                        + {s}
                      </button>
                    ))}
                  </div>
                </>
              ) : (
                <>
                  <div className="field-label">Lý do follow-up</div>
                  <input className="input mb-3" autoFocus
                    placeholder="VD: Gọi lại tư vấn combo gym, nhắc khách hết hàng Whey..."
                    value={reason} onChange={(e)=>setReason(e.target.value)}/>
                  <div className="row gap-1 mb-4" style={{flexWrap:'wrap'}}>
                    <span className="text-xs fg-muted">Gợi ý:</span>
                    {[
                      'Gọi lại tư vấn combo',
                      'Nhắc khách sắp hết hàng',
                      'Giới thiệu sản phẩm mới',
                      'Hỏi feedback sau mua',
                      'Win-back khách lâu chưa mua',
                    ].map(s => (
                      <button key={s} className="btn btn-secondary btn-sm" style={{fontSize:11,padding:'2px 10px'}} onClick={() => setReason(s)}>
                        {s}
                      </button>
                    ))}
                  </div>

                  <div className="grid grid-2 mb-3">
                    <div>
                      <div className="field-label">Ngày</div>
                      <input className="input tnum" type="date" value={date} onChange={(e)=>setDate(e.target.value)}/>
                    </div>
                    <div>
                      <div className="field-label">Giờ</div>
                      <input className="input tnum" type="time" value={time} onChange={(e)=>setTime(e.target.value)}/>
                    </div>
                  </div>
                  <div className="row gap-1 mb-3">
                    <span className="text-xs fg-muted">Nhanh:</span>
                    {[
                      {l:'Trong 1 giờ', d:'2026-05-15', t:'15:30'},
                      {l:'Hôm nay 17:00', d:'2026-05-15', t:'17:00'},
                      {l:'Ngày mai 10:00', d:'2026-05-16', t:'10:00'},
                      {l:'+ 3 ngày', d:'2026-05-18', t:'10:00'},
                      {l:'+ 1 tuần', d:'2026-05-22', t:'10:00'},
                    ].map(s => (
                      <button key={s.l} className="btn btn-ghost btn-sm" style={{fontSize:11,padding:'2px 8px'}}
                        onClick={() => { setDate(s.d); setTime(s.t); }}>
                        {s.l}
                      </button>
                    ))}
                  </div>

                  <div className="field-label">Kênh liên hệ</div>
                  <div className="row gap-1" style={{flexWrap:'wrap'}}>
                    {['Gọi điện','Zalo','SMS','Email','Cửa hàng'].map(c => (
                      <button key={c}
                        className={channel===c ? 'btn btn-cta btn-sm' : 'btn btn-secondary btn-sm'}
                        onClick={() => setChannel(c)}>
                        {c === customer.preferredContact && '★ '}{c}
                      </button>
                    ))}
                  </div>
                  <div className="text-xs fg-muted mt-2">★ Kênh khách ưa thích</div>
                </>
              )}
            </div>

            {/* Footer */}
            <div style={{padding:'var(--space-3) var(--space-5)',background:'var(--bg-soft)',borderTop:'1px solid var(--border-1)',display:'flex',gap:'var(--space-3)',alignItems:'center'}}>
              <div className="text-xs fg-muted">
                {isNote ? 'Ghi chú sẽ hiển thị ở hồ sơ 360° của khách' : 'Hệ thống sẽ tự nhắc bạn đúng giờ qua notification'}
              </div>
              <div style={{flex:1}}/>
              <button className="btn btn-secondary" onClick={onClose}>Huỷ</button>
              <button className="btn btn-cta"
                onClick={handleSave}
                disabled={isNote ? !text.trim() : !reason.trim()}>
                <Icon name="check" size={14}/>{isNote ? 'Lưu ghi chú' : 'Đặt lịch'}
              </button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

window.QuickActionModal = QuickActionModal;

// ===========================================================
// "Ghi nhận đơn hàng" modal
// In-store & telesale dùng để lưu LỊCH SỬ MUA của khách,
// đơn thực tế được tạo ở hệ thống POS bên ngoài.
// ===========================================================
function LogOrderModal({ subject, customer, mode = 'b2c', onClose, onSave }) {
  const subj = subject || customer; // back-compat
  const isB2B = mode === 'b2b';
  const priceOf = (p) => isB2B ? p.b2bPrice : p.price;
  const refLabel = isB2B ? 'Mã đơn Sapo (tham chiếu)' : 'Mã đơn POS (tham chiếu, tuỳ chọn)';
  const refPlaceholder = isB2B ? 'VD: SP-2026-05-00821' : 'VD: POS-Q1-2026-99821';
  const refExternal = isB2B ? 'Sapo' : 'POS';
  const [items, setItems] = useState([]);
  const [search, setSearch] = useState('');
  const [channel, setChannel] = useState(isB2B ? 'sapo' : 'store');
  const [posRef, setPosRef] = useState('');
  const [orderDate, setOrderDate] = useState('2026-05-13');
  const [orderTime, setOrderTime] = useState('14:30');
  const [note, setNote] = useState('');
  const [overrideTotal, setOverrideTotal] = useState(null);

  const filtered = useMemo(() => {
    if (!search) return D.products.slice(0, 8);
    const s = search.toLowerCase();
    return D.products.filter(p => p.name.toLowerCase().includes(s) || p.sku.toLowerCase().includes(s) || p.cat.toLowerCase().includes(s)).slice(0, 8);
  }, [search]);

  const addProduct = (sku) => {
    setItems(items => {
      const e = items.find(i => i.sku === sku);
      if (e) return items.map(i => i.sku === sku ? {...i, qty: i.qty + 1} : i);
      return [...items, { sku, qty: 1 }];
    });
  };
  const removeItem = (sku) => setItems(items => items.filter(i => i.sku !== sku));
  const updateQty = (sku, d) => setItems(items => items.map(i => i.sku === sku ? {...i, qty: Math.max(0, i.qty + d)} : i).filter(i => i.qty > 0));

  const rich = items.map(i => ({ ...i, ...D.products.find(p => p.sku === i.sku) }));
  const subtotal = rich.reduce((s, i) => s + (priceOf(i) * i.qty), 0);
  const total = overrideTotal != null ? overrideTotal : subtotal;
  const canSave = items.length > 0;

  return (
    <div className="drawer-overlay" style={{justifyContent:'center',alignItems:'center'}} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()}
        style={{background:'var(--bg-page)',width:'min(880px, 94vw)',maxHeight:'90vh',display:'flex',flexDirection:'column',borderRadius:'var(--radius-lg)',overflow:'hidden',boxShadow:'var(--shadow-pop)',animation:'slidein 0.28s var(--ease-out)'}}>
        {/* Header */}
        <div style={{padding:'var(--space-5) var(--space-6)',background:'var(--vs-dark-blue)',color:'#fff',display:'flex',gap:'var(--space-4)',alignItems:'center'}}>
          <div style={{width:44,height:44,borderRadius:'50%',background:'var(--vs-light-blue)',color:'var(--vs-dark-blue)',display:'flex',alignItems:'center',justifyContent:'center'}}>
            <Icon name="receipt" size={22}/>
          </div>
          <div style={{flex:1}}>
            <div className="eyebrow" style={{color:'var(--vs-light-blue)'}}>Lưu lịch sử mua hàng</div>
            <h2 style={{margin:'2px 0 0',fontFamily:'var(--font-display)',fontSize:20,fontWeight:700,color:'#fff'}}>Ghi nhận đơn — {subj.name}</h2>
            <div className="text-xs" style={{color:'rgba(255,255,255,0.7)',marginTop:2}}>
              {isB2B ? <>Đối tác {subj.type || ''} · {subj.tier} · <span className="tnum">{subj.phone}</span> · Bảng giá {subj.priceList}</>
                     : <>Khách hạng {subj.tier} · <span className="tnum">{subj.phone}</span> · ID {subj.id}</>}
            </div>
          </div>
          <button className="close" onClick={onClose}>
            <Icon name="close" size={18}/>
          </button>
        </div>

        {/* Info banner */}
        <div className="banner" style={{margin:'var(--space-4) var(--space-6) 0',borderRadius:'var(--radius-md)'}}>
          <Icon name="zap" size={16}/>
          <div className="text-sm" style={{flex:1}}>
            Đơn hàng thật được tạo trên hệ thống <b>{refExternal}</b>. CRM chỉ lưu lại <b>sản phẩm {isB2B ? 'đối tác đã mua' : 'khách đã mua'}</b> để theo dõi lịch sử + gợi ý cross-sell.
          </div>
        </div>

        {/* Body */}
        <div style={{padding:'var(--space-5) var(--space-6)',overflow:'auto',flex:1}}>
          {/* Search + selected items */}
          <div className="field-label">Sản phẩm khách đã mua</div>
          <div className="topbar-search mb-3">
            <Icon name="search" size={14} style={{color:'var(--fg-muted)'}}/>
            <input placeholder="Tìm theo tên, SKU, danh mục — VD: Whey, Multi, TVS-1001..."
              value={search} onChange={(e)=>setSearch(e.target.value)}/>
          </div>

          {/* Suggestions */}
          {search && (
            <div className="card mb-3" style={{padding:6}}>
              {filtered.map(p => (
                <button key={p.sku} onClick={() => { addProduct(p.sku); setSearch(''); }}
                  style={{display:'flex',alignItems:'center',gap:12,padding:'10px 12px',width:'100%',background:'none',border:'none',cursor:'pointer',borderRadius:'var(--radius-sm)',textAlign:'left'}}
                  className="hover-row">
                  <div style={{width:36,height:36,background:'var(--bg-soft)',borderRadius:4,display:'flex',alignItems:'center',justifyContent:'center',color:'var(--vs-light-blue)'}}>
                    <Icon name="pill" size={18}/>
                  </div>
                  <div style={{flex:1}}>
                    <div className="strong text-sm fg-1">{p.name}</div>
                    <div className="text-xs fg-muted">{p.sku} · {p.cat}</div>
                  </div>
                  <div className="strong tnum fg-1">{fmt.vndFull(priceOf(p))}</div>
                  <Icon name="plus" size={14} style={{color:'var(--vs-light-blue)'}}/>
                </button>
              ))}
            </div>
          )}

          {/* Quick add — commonly bought by this customer */}
          {!search && (
            <div className="mb-4">
              <div className="text-xs fg-muted mb-2">{isB2B ? 'Bảng giá ' + (subj.priceList || 'B2B') + ' ÷ gợi ý đối tác thường đặt:' : 'Gợi ý theo lịch sử của khách:'}</div>
              <div className="row gap-2" style={{flexWrap:'wrap'}}>
                {D.products.slice(0,5).map(p => (
                  <button key={p.sku} className="btn btn-secondary btn-sm" onClick={() => addProduct(p.sku)}>
                    <Icon name="plus" size={12}/>{p.name.split('—')[0].trim()}
                  </button>
                ))}
              </div>
            </div>
          )}

          {/* Cart preview */}
          {rich.length > 0 ? (
            <div className="card" style={{padding:0,marginBottom:'var(--space-4)'}}>
              {rich.map(it => (
                <div key={it.sku} style={{display:'flex',gap:12,padding:'12px 16px',borderBottom:'1px solid var(--border-1)',alignItems:'center'}}>
                  <div style={{width:36,height:36,background:'var(--bg-soft)',borderRadius:4,display:'flex',alignItems:'center',justifyContent:'center',color:'var(--vs-light-blue)',flexShrink:0}}>
                    <Icon name="pill" size={18}/>
                  </div>
                  <div style={{flex:1,minWidth:0}}>
                    <div className="strong text-sm fg-1" style={{overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{it.name}</div>
                    <div className="text-xs fg-muted tnum">{fmt.vndFull(priceOf(it))}{isB2B && <span style={{marginLeft:6,color:'var(--vs-light-blue)'}}>(B2B)</span>}</div>
                  </div>
                  <div className="row gap-1">
                    <button className="btn btn-icon btn-sm btn-secondary" onClick={() => updateQty(it.sku, -1)}>−</button>
                    <span className="tnum bold" style={{minWidth:20,textAlign:'center',color:'var(--fg-1)'}}>{it.qty}</span>
                    <button className="btn btn-icon btn-sm btn-secondary" onClick={() => updateQty(it.sku, 1)}>+</button>
                  </div>
                  <div className="strong tnum fg-1" style={{minWidth:100,textAlign:'right'}}>{fmt.vndFull(priceOf(it) * it.qty)}</div>
                  <button className="btn btn-icon btn-sm btn-ghost" onClick={() => removeItem(it.sku)}>
                    <Icon name="close" size={12}/>
                  </button>
                </div>
              ))}
            </div>
          ) : (
            <div className="empty" style={{padding:'var(--space-8) var(--space-4)'}}>
              <div className="icon-wrap"><Icon name="cart" size={20}/></div>
              <div className="text-sm">Chưa có sản phẩm</div>
              <div className="text-xs">Tìm sản phẩm ở trên hoặc click vào gợi ý nhanh</div>
            </div>
          )}

          {/* Meta fields */}
          <div className="grid grid-2 mt-4 mb-4">
            <div>
              <div className="field-label">Kênh bán</div>
              {isB2B ? (
                <Segmented value={channel} options={[
                  {value:'sapo',    label:'Sapo'},
                  {value:'direct',  label:'Trực tiếp'},
                  {value:'distrib', label:'Phn phối'},
                ]} onChange={setChannel}/>
              ) : (
                <Segmented value={channel} options={[
                  {value:'store', label:'Cửa hàng'},
                  {value:'telesale', label:'Telesale'},
                  {value:'web', label:'Web/App'},
                ]} onChange={setChannel}/>
              )}
            </div>
            <div>
              <div className="field-label">{refLabel}</div>
              <input className="input tnum" placeholder={refPlaceholder} value={posRef} onChange={(e) => setPosRef(e.target.value)}/>
            </div>
            <div>
              <div className="field-label">Ngày mua</div>
              <input className="input tnum" type="date" value={orderDate} onChange={(e) => setOrderDate(e.target.value)}/>
            </div>
            <div>
              <div className="field-label">Giờ</div>
              <input className="input tnum" type="time" value={orderTime} onChange={(e) => setOrderTime(e.target.value)}/>
            </div>
          </div>

          <div>
            <div className="field-label">Ghi chú (tuỳ chọn)</div>
            <textarea className="textarea" placeholder={isB2B ? 'VD: Đối tác đặt cho đợt chuẩn bị cuối tháng, giao trước 20/05...' : 'VD: Khách hỏi thêm về vị mới, đã tư vấn combo gym tăng cơ...'}
              value={note} onChange={(e)=>setNote(e.target.value)} style={{minHeight:60}}/>
          </div>
        </div>

        {/* Footer */}
        <div style={{padding:'var(--space-4) var(--space-6)',borderTop:'1px solid var(--border-1)',background:'var(--bg-soft)',display:'flex',gap:'var(--space-4)',alignItems:'center'}}>
          <div>
            <div className="text-xs fg-muted">Tổng giá trị đơn</div>
            <div className="row gap-2" style={{alignItems:'baseline'}}>
              <div className="tnum bold" style={{fontSize:22,color:'var(--vs-dark-blue)',fontFamily:'var(--font-display)'}}>
                {fmt.vndFull(total)}
              </div>
              {overrideTotal != null && overrideTotal !== subtotal && (
                <span className="text-xs fg-muted" style={{textDecoration:'line-through'}}>{fmt.vndFull(subtotal)}</span>
              )}
              {rich.length > 0 && overrideTotal == null && (
                <button className="btn btn-ghost btn-sm" onClick={() => { const v = prompt(isB2B ? 'Tổng đơn thực trên Sapo (đã áp chiết khấu):' : 'Tổng đơn thực trên POS (đã trừ khuyến mãi):', subtotal); if (v != null && !isNaN(+v)) setOverrideTotal(+v); }}>
                  Sửa tổng
                </button>
              )}
            </div>
          </div>
          <div style={{flex:1}}/>
          <button className="btn btn-secondary" onClick={onClose}>Huỷ</button>
          <button className="btn btn-cta btn-lg" disabled={!canSave} onClick={() => onSave && onSave({items: rich, total, channel, posRef, orderDate, orderTime, note})}>
            <Icon name="check" size={16}/>Lưu lịch sử mua
          </button>
        </div>
      </div>
    </div>
  );
}

window.LogOrderModal = LogOrderModal;
