// dashboard.jsx — trang chủ portal: KPI, ứng dụng ghim, và bảng widget module tuỳ chỉnh
// (kéo sắp xếp / thu nhỏ / ẩn / đổi kích thước). Số liệu THẬT từ state (p.*).

/* ---- khung widget: kéo-sắp-xếp / ẩn / thu nhỏ, chia sẻ qua context ---- */
const DashWidgetCtx = React.createContext(null);

// Khung card mỗi widget module render qua. Header mang nút Thêm + Xem tất cả
// cùng các nút grip / thu nhỏ / ẩn. Vẫn chạy độc lập (không có context) được.
function WidgetShell({ wid, icon, iconColor, title, onViewAll, onNew, newLabel, newIcon, children, bodyStyle }) {
  const dash = React.useContext(DashWidgetCtx);
  const { t, lang } = useLang();
  const cardRef = React.useRef(null);
  const collapsed = !!(dash && dash.isCollapsed(wid));
  const dragging = !!(dash && dash.draggingId === wid);
  const size = dash ? dash.getSize(wid) : { span:1 };

  // kéo cạnh phải: CHỈ đổi độ rộng (số cột 1–3) — chiều cao luôn tự căn đều theo hàng (OCD).
  const onResizeDown = e => {
    if (!dash) return;
    e.preventDefault(); e.stopPropagation();
    const card = cardRef.current, grid = card.parentNode;
    const gap = 14;
    const cols = getComputedStyle(grid).gridTemplateColumns.split(' ').filter(Boolean).length || 1;
    const colW = (grid.clientWidth - gap * (cols - 1)) / cols;
    const startX = e.clientX;
    const startSpan = Math.min(size.span || 1, cols);
    const startPxW = startSpan * colW + (startSpan - 1) * gap;
    document.body.style.userSelect = 'none';
    const move = ev => {
      const dx = ev.clientX - startX;
      let span = Math.round((startPxW + dx + gap) / (colW + gap));
      span = Math.max(1, Math.min(cols, span));
      dash.setSize(wid, { span });
    };
    const up = () => {
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
      document.body.style.userSelect = '';
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };

  const cardStyle = size.span > 1 ? { gridColumn: 'span ' + size.span } : undefined;
  const bStyle = { ...(bodyStyle || { paddingTop:6 }) };

  return (
    <div ref={cardRef} className={'card widget-card' + (dragging ? ' is-dragging' : '') + (collapsed ? ' is-collapsed' : '')} style={cardStyle}
      onDragEnter={() => dash && dash.onDragEnter(wid)}
      onDragOver={e => { if (dash && dash.draggingId != null) e.preventDefault(); }}>
      <div className="card-head">
        <div className="flex items-center g8" style={{ minWidth:0 }}>
          {dash && (
            <span className="wg-grip" title={lang === 'vi' ? 'Kéo để sắp xếp' : 'Drag to reorder'} draggable
              onDragStart={e => { e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/plain', wid); if (cardRef.current) try { e.dataTransfer.setDragImage(cardRef.current, 24, 20); } catch (err) {} dash.onDragStart(wid); }}
              onDragEnd={() => dash.onDragEnd()}><i className="bi bi-grip-vertical"></i></span>
          )}
          <h3 className="truncate"><i className={'bi ' + icon} style={{ color:iconColor, marginRight:6 }}></i>{title}</h3>
        </div>
        <div className="flex items-center" style={{ gap:6, flexShrink:0 }}>
          {onNew && <button className="btn btn-primary btn-sm wg-actbtn" title={newLabel} aria-label={newLabel} onClick={onNew}><i className={'bi ' + (newIcon || 'bi-plus-lg')}></i></button>}
          {onViewAll && <button className="btn btn-ghost btn-sm wg-actbtn" title={t('c.viewAll')} aria-label={t('c.viewAll')} onClick={onViewAll}><i className="bi bi-arrow-right"></i></button>}
          {dash && <button className="wg-icobtn" title={collapsed ? (lang === 'vi' ? 'Mở rộng' : 'Expand') : (lang === 'vi' ? 'Thu nhỏ' : 'Collapse')} onClick={() => dash.toggleCollapse(wid)}><i className={'bi ' + (collapsed ? 'bi-chevron-down' : 'bi-chevron-up')}></i></button>}
          {dash && <button className="wg-icobtn" title={lang === 'vi' ? 'Ẩn widget' : 'Hide widget'} onClick={() => dash.hide(wid)}><i className="bi bi-eye-slash"></i></button>}
        </div>
      </div>
      {!collapsed && <div className="card-body" style={bStyle}>{children}</div>}
      {dash && !collapsed && <span className="wg-resize" title={lang === 'vi' ? 'Kéo để đổi độ rộng (số cột)' : 'Drag to change width'} onPointerDown={onResizeDown}></span>}
    </div>
  );
}

// Điều phối lưới widget module: thứ tự + ẩn + thu nhỏ (đã lưu localStorage),
// kéo-để-sắp-xếp, và popover tuỳ chỉnh hiện/ẩn widget.
function WidgetBoard() {
  const p = usePortal();
  const { tt, lang } = useLang();
  const WIDGETS = { mail:EmailWidget, customers:CustomerWidget, contacts:ContactWidget, contracts:ContractWidget, vendors:VendorWidget, finance:FinanceWidget, deals:DealWidget, support:SupportWidget, inventory:InventoryWidget, products:ProductWidget, quotes:QuoteWidget, users:UserWidget, website:WebsiteWidget };
  const DEFAULT_ORDER = ['mail', 'customers', 'contacts', 'contracts', 'vendors', 'finance', 'deals', 'support', 'inventory', 'products', 'quotes', 'users', 'website'];
  const available = DEFAULT_ORDER.filter(id => WIDGETS[id] && p.apps.some(a => a.id === id));

  // Nguồn chân lý = context (theo NGƯỜI DÙNG, đồng bộ đa máy qua profiles.meta.dashLayout — xem main.jsx).
  const dl = p.dashLayout || {};
  const order = Array.isArray(dl.order) ? dl.order : DEFAULT_ORDER;
  const hidden = Array.isArray(dl.hidden) ? dl.hidden : [];
  const collapsed = Array.isArray(dl.collapsed) ? dl.collapsed : [];
  const sizes = (dl.sizes && typeof dl.sizes === 'object') ? dl.sizes : {};
  const [dragId, setDragId] = React.useState(null);
  const dragRef = React.useRef(null);
  const [custOpen, setCustOpen] = React.useState(false);

  const eff = [...order.filter(id => available.includes(id)), ...available.filter(id => !order.includes(id))];
  const visible = eff.filter(id => !hidden.includes(id));
  const save = patch => p.saveDashLayout({ order:eff, hidden, collapsed, sizes, ...patch });

  const moveBefore = (drag, target) => {
    const arr = eff.filter(x => x !== drag);
    const i = arr.indexOf(target);
    if (i < 0) arr.push(drag); else arr.splice(i, 0, drag);
    save({ order:arr });
  };

  const api = {
    draggingId: dragId,
    isCollapsed: id => collapsed.includes(id),
    toggleCollapse: id => save({ collapsed: collapsed.includes(id) ? collapsed.filter(x => x !== id) : [...collapsed, id] }),
    hide: id => save({ hidden: hidden.includes(id) ? hidden : [...hidden, id] }),
    onDragStart: id => { dragRef.current = id; setDragId(id); },
    onDragEnter: id => { const d = dragRef.current; if (d && d !== id) moveBefore(d, id); },
    onDragEnd: () => { dragRef.current = null; setDragId(null); },
    getSize: id => sizes[id] || { span:1 },
    setSize: (id, s) => save({ sizes: { ...sizes, [id]: { ...(sizes[id] || { span:1 }), ...s } } }),
  };

  if (!available.length) return null;
  return (
    <div style={{ marginBottom:14 }}>
      <div className="flex justify-between items-center" style={{ margin:'0 2px 10px' }}>
        <h2 style={{ margin:0, fontSize:'var(--fs-xl)', fontWeight:600, letterSpacing:'-.01em' }}>{lang === 'vi' ? 'Ứng dụng' : 'Modules'}</h2>
        <div style={{ position:'relative' }}>
          <button className="btn btn-sm" onClick={() => setCustOpen(o => !o)}><i className="bi bi-sliders2"></i>{lang === 'vi' ? 'Tùy chỉnh' : 'Customize'}</button>
          {custOpen && (
            <React.Fragment>
              <div className="wg-pop-scrim" onClick={() => setCustOpen(false)}></div>
              <div className="wg-pop">
                <div className="wg-pop-hd">{lang === 'vi' ? 'Hiện / ẩn widget' : 'Show / hide widgets'}</div>
                {available.map(id => {
                  const app = p.apps.find(a => a.id === id) || {};
                  const on = !hidden.includes(id);
                  return (
                    <div key={id} className="wg-pop-row" onClick={() => save({ hidden: on ? [...hidden, id] : hidden.filter(x => x !== id) })}>
                      <span className="wg-pop-ic" style={{ background:app.color }}><i className={'bi ' + (app.icon || 'bi-app')}></i></span>
                      <span className="grow truncate">{tt(app.name)}</span>
                      <i className={'bi ' + (on ? 'bi-eye' : 'bi-eye-slash')} style={{ color:on ? 'var(--primary)' : 'var(--text-subtle)' }}></i>
                    </div>
                  );
                })}
                <div className="wg-pop-foot"><button className="btn btn-ghost btn-sm" onClick={() => p.saveDashLayout({})}><i className="bi bi-arrow-counterclockwise"></i>{lang === 'vi' ? 'Khôi phục mặc định' : 'Reset layout'}</button></div>
              </div>
            </React.Fragment>
          )}
        </div>
      </div>
      {visible.length === 0
        ? <EmptyState icon="bi-grid" text={lang === 'vi' ? 'Chưa có widget nào hiển thị — bấm “Tùy chỉnh” để bật lại' : 'No widgets shown — use Customize to re-enable'} />
        : (
          <DashWidgetCtx.Provider value={api}>
            <div className="dash-grid wgrid">{visible.map(id => { const W = WIDGETS[id]; return <W key={id} />; })}</div>
          </DashWidgetCtx.Provider>
        )}
    </div>
  );
}

function Dashboard() {
  const p = usePortal();
  const { t, tt, lang } = useLang();
  const me = p.me;

  const pinnedApps = p.apps.filter(a => a.id !== 'mail' && p.pinned.includes(a.id));

  return (
    <div className="page pagefade">
      <div className="page-head">
        <div>
          <h1>{t('dash.hello')}, {me.name.split(' ').slice(-1)[0]} 👋</h1>
          <div className="sub">{lang === 'vi' ? 'Đây là tổng quan hoạt động của bạn hôm nay.' : "Here's your activity overview for today."}</div>
        </div>
        <div className="flex g8">
          <button className="btn" onClick={() => p.navigate({ name:'allapps' })}><i className="bi bi-grid-3x3-gap"></i>{t('nav.allApps')}</button>
          <button className="btn btn-primary" onClick={() => p.quick('mail')}><i className="bi bi-pencil-square"></i>{t('mail.compose')}</button>
        </div>
      </div>

      {/* KPI strip — số liệu THẬT từ state (p.*), card đồng nhất chiều cao */}
      <div className="kpi-strip" style={{ gridTemplateColumns:'repeat(3, 1fr)' }}>
        <div style={{ cursor:'pointer' }} onClick={() => p.navigate({ name:'module', module:'contracts', sub:'overview' })}>
          <Kpi label={lang === 'vi' ? 'HĐ đến hạn' : 'Contracts due'} value={p.contracts.filter(c => contractStatus(c) === 'expiring').length} icon="bi-alarm" />
        </div>
        <div style={{ cursor:'pointer' }} onClick={() => p.navigate({ name:'module', module:'customers' })}>
          <Kpi label={t('kpi.customers')} value={p.customers.length} icon="bi-building" />
        </div>
        <div style={{ cursor:'pointer' }} onClick={() => p.navigate({ name:'module', module:'contacts' })}>
          <Kpi label={t('kpi.contacts')} value={p.contacts.length} icon="bi-person-vcard" />
        </div>
      </div>

      {/* ứng dụng ghim */}
      <div className="dash-grid" style={{ marginBottom:14 }}>
        <div className="card span3">
          <div className="card-head"><h3>{t('dash.pinned')}</h3><button className="btn btn-ghost btn-sm" onClick={() => p.navigate({ name:'allapps' })}><i className="bi bi-plus-lg"></i>{t('apps.pin')}</button></div>
          <div className="card-body" style={{ paddingTop:10 }}>
            <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(170px, 1fr))', gap:8 }}>
              {pinnedApps.slice(0, 10).map(a => (
                <button key={a.id} className="app-tile" style={{ padding:10 }} onClick={() => p.openApp(a)}>
                  <span className="ic" style={{ background:a.color }}><i className={'bi ' + a.icon}></i></span>
                  <div style={{ minWidth:0 }}><div className="at-name truncate">{tt(a.name)}</div></div>
                </button>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* widget module thật — tuỳ chỉnh: kéo sắp xếp, thu nhỏ, hiện/ẩn (chỉ widget của module có trên hệ thống) */}
      <WidgetBoard />
    </div>
  );
}
Object.assign(window, { Dashboard, WidgetShell, WidgetBoard, DashWidgetCtx });
