// ============ PRISMA · PANEL CLIENTE — screens ============
const { useState: useSS, useMemo: useSM, useRef: useSR, useEffect: useSE } = React;

// ---- LOGIN ----
const ClScreenLogin = ({ onLogin, error }) => {
  const [email, setEmail] = useSS('');
  const [pass, setPass] = useSS('');
  const [loading, setLoading] = useSS(false);
  const [focus, setFocus] = useSS(null);

  const fieldStyle = (id) => ({
    width: '100%', background: 'var(--bg-0)', color: 'var(--txt)',
    border: '1px solid ' + (focus === id ? 'var(--line-strong)' : 'var(--line)'),
    borderRadius: 'var(--r-md)', padding: '11px 13px 11px 38px',
    fontSize: 14, outline: 'none', transition: 'border-color .15s',
  });

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    await onLogin(email, pass);
    setLoading(false);
  };

  return (
    <div style={{
      position: 'relative', minHeight: '100%', display: 'grid', placeItems: 'center',
      background: 'var(--bg-0)', padding: 24, overflow: 'hidden',
    }}>
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: 'radial-gradient(580px 420px at 50% 30%, rgba(232,23,93,0.10), transparent 68%), radial-gradient(480px 360px at 72% 82%, rgba(59,158,224,0.07), transparent 70%)',
      }} />
      <form className="slide-up" onSubmit={handleSubmit} style={{
        position: 'relative', width: 360, maxWidth: '100%',
        background: 'var(--bg-1)', border: '1px solid var(--line)',
        borderRadius: 16, padding: '34px 30px 30px',
        boxShadow: '0 30px 80px rgba(0,0,0,0.55)',
      }}>
        <img src="assets/logo-cropped.png" alt="Prisma" style={{ height: 34, display: 'block' }} />
        <h1 style={{ marginTop: 22, fontSize: 22, fontWeight: 700, letterSpacing: '-0.01em' }}>Portal de clientes</h1>
        <p style={{ marginTop: 6, fontSize: 13, color: 'var(--txt-mut)' }}>Acceso exclusivo para empresas con proyectos en Prisma Studios.</p>

        {error && (
          <div style={{
            marginTop: 16, padding: '10px 12px', borderRadius: 8,
            background: window.hexA('#EF4444', 0.1), border: '1px solid ' + window.hexA('#EF4444', 0.3),
            fontSize: 13, color: '#EF4444',
          }}>{error}</div>
        )}

        <div style={{ display: 'grid', gap: 14, marginTop: error ? 14 : 24 }}>
          <label style={{ display: 'block' }}>
            <div style={{ fontSize: 12, fontWeight: 500, color: 'var(--txt-mut)', marginBottom: 7 }}>Email</div>
            <div style={{ position: 'relative' }}>
              <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--txt-dim)', display: 'grid' }}>
                <window.CiMail size={15} />
              </span>
              <input type="email" value={email} onChange={e => setEmail(e.target.value)}
                onFocus={() => setFocus('email')} onBlur={() => setFocus(null)}
                style={fieldStyle('email')} required />
            </div>
          </label>
          <label style={{ display: 'block' }}>
            <div style={{ fontSize: 12, fontWeight: 500, color: 'var(--txt-mut)', marginBottom: 7 }}>Contraseña</div>
            <div style={{ position: 'relative' }}>
              <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--txt-dim)', display: 'grid' }}>
                <window.CiLock size={15} />
              </span>
              <input type="password" value={pass} onChange={e => setPass(e.target.value)}
                onFocus={() => setFocus('pass')} onBlur={() => setFocus(null)}
                style={fieldStyle('pass')} required />
            </div>
          </label>
        </div>

        <button type="submit" disabled={loading} style={{
          width: '100%', marginTop: 22, background: '#fff', color: '#000',
          border: 'none', borderRadius: 'var(--r-md)', padding: '12px',
          fontSize: 14, fontWeight: 700, transition: 'opacity .15s',
          opacity: loading ? 0.6 : 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        }}>
          {loading ? <><window.CiSpinner size={16} /> Ingresando…</> : 'Ingresar'}
        </button>
        <div style={{ marginTop: 18, textAlign: 'center', fontSize: 11.5, color: 'var(--txt-dim)' }}>
          Prisma Studios · Portal exclusivo para clientes
        </div>
      </form>
    </div>
  );
};

// ---- DASHBOARD ----
const ClScreenDashboard = ({ building, counts }) => {
  const [events, setEvents] = useSS([]);
  const [loading, setLoading] = useSS(true);
  const [lastUpdate, setLastUpdate] = useSS(Date.now());
  const [refreshKey, setRefreshKey] = useSS(0);
  const [minAgo, setMinAgo] = useSS(0);
  const ac = window.acHex(building.accent);

  // Auto-refresh cada 5 minutos
  useSE(() => {
    const id = setInterval(() => setRefreshKey(k => k + 1), 5 * 60 * 1000);
    return () => clearInterval(id);
  }, []);

  // Actualizar label "hace X min" cada minuto
  useSE(() => {
    const id = setInterval(() => {
      setMinAgo(Math.floor((Date.now() - lastUpdate) / 60000));
    }, 60 * 1000);
    return () => clearInterval(id);
  }, [lastUpdate]);

  useSE(() => {
    let active = true;
    setLoading(true);
    const since = new Date(Date.now() - 24 * 3600 * 1000).toISOString();
    window._sb
      .from('eventos')
      .select('tipo, valor, created_at')
      .eq('edificio_id', building.id)
      .gte('created_at', since)
      .order('created_at', { ascending: false })
      .limit(200)
      .then(({ data }) => {
        if (active) {
          setEvents(data || []);
          setLoading(false);
          setLastUpdate(Date.now());
          setMinAgo(0);
        }
      });
    return () => { active = false; };
  }, [building.id, refreshKey]);

  // Derivar stats
  const stats = useSM(() => {
    const visitas   = events.filter(e => e.tipo === 'vista_seccion').length;
    const clicks    = events.filter(e => e.tipo === 'click_unidad').length;
    const whatsapp  = events.filter(e => e.tipo === 'click_whatsapp').length;

    const unitCounts = events
      .filter(e => e.tipo === 'click_unidad' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const topUnit = Object.entries(unitCounts).sort((a, b) => b[1] - a[1])[0];

    const tourCounts = events
      .filter(e => e.tipo === 'click_360' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const top360 = Object.entries(tourCounts).sort((a, b) => b[1] - a[1])[0];

    const pisoCounts = events
      .filter(e => e.tipo === 'click_piso' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const topFloor = Object.entries(pisoCounts).sort((a, b) => b[1] - a[1])[0];

    return {
      visitas, clicks, whatsapp,
      topUnit: topUnit ? topUnit[0] : '—',
      top360:  top360  ? top360[0]  : '—',
      topFloor: topFloor ? topFloor[0] : '—',
    };
  }, [events]);

  const eventIcon = { view: window.CiEye, whatsapp: window.CiChat, tour: window.CiTour, pdf: window.CiPdf };
  const eventAcc  = { view: building.accent, whatsapp: 'teal', tour: 'azul', pdf: 'indigo' };

  const recentEvents = useSM(() => events.slice(0, 5).map(e => {
    const kind = window.CL_TIPO_KIND[e.tipo] || 'view';
    const hora = new Date(e.created_at).toLocaleTimeString('es-AR', { hour: '2-digit', minute: '2-digit' });
    return { time: hora, type: window.CL_TIPO_LABEL[e.tipo] || e.tipo, detail: e.valor || '', kind };
  }), [events]);

  return (
    <div className="fade-in cl-page-pad" style={{ padding: 24, maxWidth: 1080, margin: '0 auto' }}>
      <window.CiKicker>Resumen</window.CiKicker>
      <div style={{ fontSize: 20, fontWeight: 700, marginTop: 5 }}>{building.company || building.name}</div>
      <div style={{ fontSize: 13, color: 'var(--txt-mut)', marginTop: 4 }}>
        {building.name} · {minAgo === 0 ? 'actualizado ahora' : `hace ${minAgo} min`}
      </div>

      {/* disponibilidad */}
      <div className="cl-grid3" style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 14, marginTop: 20 }}>
        <window.CiStatCard label="Unidades disponibles" value={counts.disponible} accent="ok" big />
        <window.CiStatCard label="Unidades reservadas"  value={counts.reservado}  accent="warn" big />
        <window.CiStatCard label="Unidades vendidas"    value={counts.vendido}    accent="bad" big />
      </div>

      {/* destacados showroom (últimas 24h) */}
      <window.CiCard style={{ marginTop: 14 }} pad={0}>
        <div style={{ padding: '14px 20px 12px', borderBottom: '1px solid var(--line)' }}>
          <div style={{ fontSize: 15, fontWeight: 600 }}>Destacados del showroom</div>
          <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 3 }}>Últimas 24 horas</div>
        </div>
        <div className="cl-highlight-grid" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 0 }}>
          <ClHighlightCell icon={window.CiEye}  accent={building.accent} label="Unidad más vista"  value={stats.topUnit}  />
          <ClHighlightCell icon={window.CiTour} accent="azul"  label="360° más visto"   value={stats.top360}   border />
          <ClHighlightCell icon={window.CiHome} accent="teal"  label="Piso más visto"   value={stats.topFloor} border />
        </div>
      </window.CiCard>

      {/* actividad */}
      <window.CiCard style={{ marginTop: 14 }} pad={0}>
        <div style={{ padding: '16px 20px 14px', borderBottom: '1px solid var(--line)' }}>
          <div style={{ fontSize: 15, fontWeight: 600 }}>Actividad del showroom</div>
          <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 3 }}>Últimas 24 horas</div>
          <div style={{ display: 'flex', gap: 26, marginTop: 16, flexWrap: 'wrap' }}>
            <ClMiniStat icon={window.CiEye}  value={stats.visitas}  label="visitas"             accent="azul" />
            <ClMiniStat icon={window.CiHome} value={stats.clicks}   label="clicks en unidades"  accent={building.accent} />
            <ClMiniStat icon={window.CiChat} value={stats.whatsapp} label="consultas WhatsApp"  accent="teal" />
          </div>
        </div>
        <div style={{ padding: '6px 12px 10px' }}>
          <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase',
            color: 'var(--txt-dim)', padding: '10px 8px 8px' }}>Últimos eventos</div>
          {loading ? (
            <div style={{ padding: '20px 8px', display: 'flex', alignItems: 'center', gap: 10, color: 'var(--txt-dim)' }}>
              <window.CiSpinner size={16} />
              <span style={{ fontSize: 13 }}>Cargando…</span>
            </div>
          ) : recentEvents.length === 0 ? (
            <div style={{ padding: '20px 8px', fontSize: 13, color: 'var(--txt-dim)' }}>Sin actividad en las últimas 24 horas.</div>
          ) : recentEvents.map((ev, i) => {
            const Icon = eventIcon[ev.kind] || window.CiEye;
            const evAc = window.acHex(eventAcc[ev.kind] || 'azul');
            return (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 13, padding: '10px 8px',
                borderTop: i === 0 ? 'none' : '1px solid var(--line)' }}>
                <span style={{ width: 32, height: 32, borderRadius: 8, flex: '0 0 auto',
                  background: window.hexA(evAc, 0.13), color: evAc,
                  display: 'grid', placeItems: 'center' }}>
                  <Icon size={16} />
                </span>
                <span className="u-mono" style={{ fontSize: 13, color: 'var(--txt-mut)', width: 44, flex: '0 0 auto' }}>{ev.time}</span>
                <span style={{ fontSize: 13.5, fontWeight: 600, flex: 1, minWidth: 0 }}>{ev.type}</span>
                <span style={{ fontSize: 13, color: 'var(--txt-mut)', whiteSpace: 'nowrap' }}>{ev.detail}</span>
              </div>
            );
          })}
        </div>
      </window.CiCard>
    </div>
  );
};

const ClHighlightCell = ({ icon: Icon, accent, label, value, border }) => {
  const c = window.acHex(accent);
  return (
    <div className={border ? 'cl-highlight-cell-border' : ''} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 20px',
      borderLeft: border ? '1px solid var(--line)' : 'none' }}>
      <span style={{ width: 36, height: 36, borderRadius: 9, flex: '0 0 auto',
        background: window.hexA(c, 0.13), color: c, display: 'grid', placeItems: 'center' }}>
        <Icon size={18} />
      </span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 11, color: 'var(--txt-mut)', fontWeight: 500 }}>{label}</div>
        <div style={{ fontSize: 14, fontWeight: 700, marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{value}</div>
      </div>
    </div>
  );
};

const ClMiniStat = ({ icon: Icon, value, label, accent }) => {
  const c = window.acHex(accent);
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
      <span style={{ width: 36, height: 36, borderRadius: 9, flex: '0 0 auto',
        background: window.hexA(c, 0.14), color: c, display: 'grid', placeItems: 'center' }}>
        <Icon size={18} />
      </span>
      <div>
        <div className="u-mono" style={{ fontSize: 22, fontWeight: 700, lineHeight: 1 }}>{value}</div>
        <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 2 }}>{label}</div>
      </div>
    </div>
  );
};

// ---- DISPONIBILIDAD ----
const ClAvailChip = ({ floor, pending, onClick }) => {
  const s = window.CL_STATUS[floor.status];
  const isVendido = floor.status === 'vendido';
  return (
    <button onClick={onClick} title={s.label + (pending ? ' · sin guardar' : '')} style={{
      position: 'relative', width: 58, height: 38, padding: 0, flexShrink: 0,
      borderRadius: 9, display: 'inline-grid', placeItems: 'center', overflow: 'visible',
      background: window.hexA(s.color, 0.13),
      color: s.color, fontSize: 13, fontWeight: 700, letterSpacing: '0.01em',
      border: '1.5px ' + (pending ? 'dashed ' : 'solid ') + (pending ? s.color : window.hexA(s.color, 0.35)),
      transition: 'background .12s',
    }}
      onMouseEnter={e => e.currentTarget.style.background = window.hexA(s.color, 0.22)}
      onMouseLeave={e => e.currentTarget.style.background = window.hexA(s.color, 0.13)}>
      <span style={{ position: 'relative', zIndex: 1 }}>{floor.label}</span>
      {isVendido && (
        <span style={{ position: 'absolute', left: 5, right: 5, top: '50%', height: 1.5,
          background: s.color, opacity: 0.7, transform: 'rotate(-12deg)', borderRadius: 2, zIndex: 0 }} />
      )}
      {pending && (
        <span style={{ position: 'absolute', top: -5, right: -5, width: 10, height: 10, borderRadius: 999,
          background: 'var(--pending)', border: '2px solid var(--bg-1)', zIndex: 2 }} />
      )}
    </button>
  );
};

const PER_PAGE = 10;

const ClPageNav = ({ page, total, onChange }) => {
  if (total <= 1) return null;
  const pages = total <= 7
    ? Array.from({ length: total }, (_, i) => i)
    : page < 4
      ? [...Array.from({ length: 5 }, (_, i) => i), '…', total - 1]
      : page > total - 5
        ? [0, '…', ...Array.from({ length: 5 }, (_, i) => total - 5 + i)]
        : [0, '…', page - 1, page, page + 1, '…', total - 1];

  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'center', marginTop: 14 }}>
      <button onClick={() => onChange(page - 1)} disabled={page === 0} style={{
        width: 34, height: 34, borderRadius: 8, border: '1px solid var(--line)',
        background: 'var(--bg-2)', color: page === 0 ? 'var(--txt-dim)' : 'var(--txt)',
        display: 'grid', placeItems: 'center', fontSize: 16, fontWeight: 600,
        cursor: page === 0 ? 'not-allowed' : 'pointer',
      }}>‹</button>
      {pages.map((p, i) => p === '…' ? (
        <span key={'e' + i} style={{ width: 34, textAlign: 'center', color: 'var(--txt-dim)', fontSize: 13 }}>…</span>
      ) : (
        <button key={p} onClick={() => onChange(p)} style={{
          width: 34, height: 34, borderRadius: 8, fontSize: 13, fontWeight: 600,
          border: p === page ? '1px solid var(--line-strong)' : '1px solid var(--line)',
          background: p === page ? 'var(--bg-2)' : 'transparent',
          color: p === page ? 'var(--txt)' : 'var(--txt-mut)',
        }}>{p + 1}</button>
      ))}
      <button onClick={() => onChange(page + 1)} disabled={page === total - 1} style={{
        width: 34, height: 34, borderRadius: 8, border: '1px solid var(--line)',
        background: 'var(--bg-2)', color: page === total - 1 ? 'var(--txt-dim)' : 'var(--txt)',
        display: 'grid', placeItems: 'center', fontSize: 16, fontWeight: 600,
        cursor: page === total - 1 ? 'not-allowed' : 'pointer',
      }}>›</button>
    </div>
  );
};

const ClRefreshBtn = ({ onClick }) => (
  <button onClick={onClick} title="Recargar datos" style={{
    display: 'inline-flex', alignItems: 'center', gap: 6,
    background: 'transparent', border: '1px solid var(--line)',
    borderRadius: 8, padding: '6px 12px', fontSize: 12, fontWeight: 500,
    color: 'var(--txt-mut)', cursor: 'pointer', transition: 'color .12s, border-color .12s',
  }}
    onMouseEnter={e => { e.currentTarget.style.color = 'var(--txt)'; e.currentTarget.style.borderColor = 'var(--line-strong)'; }}
    onMouseLeave={e => { e.currentTarget.style.color = 'var(--txt-mut)'; e.currentTarget.style.borderColor = 'var(--line)'; }}>
    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16M3 21v-5h5"/>
    </svg>
    Recargar
  </button>
);

const ClScreenDisponibilidad = ({ building, work, saved, onCycle, onRefresh }) => {
  const [page, setPage] = useSS(0);
  const counts = useSM(() => window.clCountStatuses(work), [work]);
  const savedFloor = (ri, fi) => saved[ri]?.floors[fi]?.status;
  const dirty = useSM(() => JSON.stringify(work) !== JSON.stringify(saved), [work, saved]);
  const totalPages = Math.ceil(work.length / PER_PAGE);
  const pageRows = work.slice(page * PER_PAGE, (page + 1) * PER_PAGE);
  const pageOffset = page * PER_PAGE;

  useSE(() => { setPage(0); }, [building.id]);

  if (work.length === 0) {
    return (
      <div className="fade-in" style={{ padding: 24, maxWidth: 1080, margin: '0 auto' }}>
        <window.CiKicker>Gestión</window.CiKicker>
        <div style={{ fontSize: 20, fontWeight: 700, marginTop: 5 }}>Estado de unidades — {building.name}</div>
        <div style={{ fontSize: 13, color: 'var(--txt-dim)', marginTop: 40, textAlign: 'center' }}>
          No hay unidades registradas para este edificio.
        </div>
      </div>
    );
  }

  return (
    <div className="fade-in cl-page-pad" style={{ padding: 24, paddingBottom: 110, maxWidth: 1080, margin: '0 auto' }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
        <div>
          <window.CiKicker>Gestión</window.CiKicker>
          <div style={{ fontSize: 20, fontWeight: 700, marginTop: 5 }}>Estado de unidades — {building.name}</div>
          <div style={{ fontSize: 13, color: 'var(--txt-mut)', marginTop: 4 }}>
            Tocá cada chip para cambiar el estado y guardá los cambios al final.
          </div>
        </div>
        <ClRefreshBtn onClick={onRefresh} />
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 18, flexWrap: 'wrap' }}>
        <window.CiSummaryPill accentKey="ok">{counts.disponible} disponibles</window.CiSummaryPill>
        <window.CiSummaryPill accentKey="warn">{counts.reservado} reservadas</window.CiSummaryPill>
        <window.CiSummaryPill accentKey="bad">{counts.vendido} vendidas</window.CiSummaryPill>
        {dirty && <span style={{ fontSize: 12, color: 'var(--txt-dim)', fontStyle: 'italic', marginLeft: 2 }}>(sin guardar)</span>}
        <span style={{ fontSize: 12, color: 'var(--txt-dim)', marginLeft: 'auto' }}>
          {work.length} unidades{totalPages > 1 ? ` · pág. ${page + 1} de ${totalPages}` : ''}
        </span>
      </div>

      <window.CiCard style={{ marginTop: 14 }} pad={0}>
        <div style={{ display: 'flex', alignItems: 'center', padding: '10px 20px', borderBottom: '1px solid var(--line)' }}>
          <div style={{ flex: 1, fontSize: 10, fontWeight: 600, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--txt-dim)' }}>Unidad</div>
          <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--txt-dim)' }}>Estado por piso</div>
        </div>
        {pageRows.map((row, ri) => {
          const globalRi = pageOffset + ri;
          return (
            <div key={row.id} className="cl-avail-row" style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '14px 20px',
              borderTop: ri === 0 ? 'none' : '1px solid var(--line)', transition: 'background .1s' }}
              onMouseEnter={e => e.currentTarget.style.background = 'rgba(255,255,255,0.025)'}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, fontWeight: 600 }}>{row.name}</div>
                <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 2 }}>{row.type}</div>
              </div>
              <div className="cl-avail-chips" style={{ display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
                {row.floors.map((f, fi) => (
                  <ClAvailChip key={f.dispId || f.label} floor={f}
                    pending={f.status !== savedFloor(globalRi, fi)}
                    onClick={() => onCycle(globalRi, fi)} />
                ))}
              </div>
            </div>
          );
        })}
      </window.CiCard>

      <ClPageNav page={page} total={totalPages} onChange={setPage} />

      <div style={{ display: 'flex', gap: 18, marginTop: 14, flexWrap: 'wrap', alignItems: 'center' }}>
        {window.CL_STATUS_CYCLE.map(k => {
          const s = window.CL_STATUS[k];
          return (
            <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 12, color: 'var(--txt-mut)' }}>
              <span style={{ width: 11, height: 11, borderRadius: 3.5,
                background: window.hexA(s.color, 0.18), border: '1px solid ' + window.hexA(s.color, 0.5) }} />
              {s.label}
            </div>
          );
        })}
        <div style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 12, color: 'var(--txt-mut)' }}>
          <span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--pending)' }} />
          Cambio sin guardar
        </div>
        <div style={{ fontSize: 11.5, color: 'var(--txt-dim)', marginLeft: 'auto' }}>
          Click en un chip para rotar el estado
        </div>
      </div>
    </div>
  );
};

// ---- PDF EXPORT ----
function printMetricas(building, pLabel, stats, bars) {
  const date = new Date().toLocaleDateString('es-AR', { day: '2-digit', month: 'long', year: 'numeric' });
  const barMax = Math.max(1, ...bars.map(b => b.value));
  const barW = Math.max(2, Math.floor(480 / bars.length) - 2);

  const barsHtml = bars.map(b => {
    const h = Math.round((b.value / barMax) * 80);
    return `<div style="display:flex;flex-direction:column;align-items:center;gap:2px">
      <span style="font-size:9px;color:#888">${b.value || ''}</span>
      <div style="width:${barW}px;height:${h}px;background:#E8175D;border-radius:2px 2px 0 0;min-height:${b.value?2:0}px"></div>
      <span style="font-size:8px;color:#aaa;writing-mode:vertical-lr;transform:rotate(180deg);max-height:24px;overflow:hidden">${b.label}</span>
    </div>`;
  }).join('');

  const topRows = (stats.topUnidades || []).map((s, i) =>
    `<tr><td style="color:#888">#${i+1}</td><td>${s.name}</td><td style="text-align:right;font-weight:600">${s.views.toLocaleString('es-AR')}</td></tr>`
  ).join('');

  const html = `<!DOCTYPE html><html><head><meta charset="UTF-8">
<title>Métricas ${building.name} — ${pLabel}</title>
<style>
  *{box-sizing:border-box;margin:0;padding:0}
  body{font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#111;padding:32px;font-size:13px}
  .header{border-bottom:3px solid #E8175D;padding-bottom:16px;margin-bottom:24px}
  .brand{font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#E8175D;margin-bottom:6px}
  h1{font-size:22px;font-weight:700;margin-bottom:4px}
  .sub{color:#666;font-size:12px}
  .grid{display:grid;gap:12px;margin-bottom:20px}
  .g3{grid-template-columns:repeat(3,1fr)}
  .g4{grid-template-columns:repeat(4,1fr)}
  .card{border:1px solid #e5e7eb;border-radius:8px;padding:12px 14px}
  .card-lbl{font-size:9px;text-transform:uppercase;letter-spacing:.08em;color:#888;margin-bottom:6px}
  .card-val{font-size:22px;font-weight:700;color:#111}
  .card-val-sm{font-size:15px;font-weight:700;color:#111}
  .section-title{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#555;margin:20px 0 10px}
  table{width:100%;border-collapse:collapse}
  th{background:#f3f4f6;padding:7px 10px;font-size:10px;text-transform:uppercase;letter-spacing:.06em;text-align:left}
  td{padding:7px 10px;border-bottom:1px solid #f0f0f0;font-size:12px}
  .conv-val{font-size:18px;font-weight:700;text-align:right}
  .footer{margin-top:32px;padding-top:12px;border-top:1px solid #eee;font-size:10px;color:#aaa;text-align:center}
  .chart{display:flex;align-items:flex-end;gap:2px;height:120px;padding:0 0 4px;margin-top:8px;overflow:hidden}
  @media print{body{padding:16px}@page{margin:16mm}}
</style></head><body>
<div class="header">
  <div class="brand">Prisma Studios · Portal de Clientes</div>
  <h1>Métricas — ${building.name}</h1>
  <p class="sub">Período: ${pLabel} &nbsp;·&nbsp; Generado el ${date}</p>
</div>

<div class="grid g3">
  <div class="card"><div class="card-lbl">Visitas totales</div><div class="card-val">${stats.visitas}</div></div>
  <div class="card"><div class="card-lbl">Sesiones únicas</div><div class="card-val">${stats.sesiones}</div></div>
  <div class="card"><div class="card-lbl">Tasa de consultas</div><div class="card-val">${stats.tasa}</div></div>
</div>
<div class="grid g4">
  <div class="card"><div class="card-lbl">Unidad más vista</div><div class="card-val-sm">${stats.topUnit}</div></div>
  <div class="card"><div class="card-lbl">Sección más vista</div><div class="card-val-sm">${stats.topSection}</div></div>
  <div class="card"><div class="card-lbl">360° más visto</div><div class="card-val-sm">${stats.top360}</div></div>
  <div class="card"><div class="card-lbl">Piso más visto</div><div class="card-val-sm">${stats.topFloor}</div></div>
</div>

<div class="section-title">Actividad por período</div>
<div class="chart">${barsHtml}</div>

<div class="section-title">Conversiones</div>
<table>
  <tr><th>Acción</th><th style="text-align:right">Cantidad</th></tr>
  <tr><td>Consultas WhatsApp</td><td class="conv-val">${stats.conversions.whatsapp}</td></tr>
  <tr><td>Descargas PDF</td><td class="conv-val">${stats.conversions.pdf}</td></tr>
  <tr><td>Recorridos 360°</td><td class="conv-val">${stats.conversions.tour}</td></tr>
</table>

${topRows ? `<div class="section-title">Unidades más vistas</div>
<table>
  <tr><th>#</th><th>Unidad</th><th style="text-align:right">Vistas</th></tr>
  ${topRows}
</table>` : ''}

<div class="footer">Prisma Studios &nbsp;·&nbsp; Portal exclusivo para clientes &nbsp;·&nbsp; ${new Date().getFullYear()}</div>
</body></html>`;

  const w = window.open('', '_blank', 'width=860,height=720');
  w.document.write(html);
  w.document.close();
  w.focus();
  setTimeout(() => w.print(), 500);
}

// ---- MÉTRICAS ----
const ClScreenMetricas = ({ building, period, setPeriod }) => {
  const [open, setOpen] = useSS(false);
  const [events, setEvents] = useSS([]);
  const [loading, setLoading] = useSS(true);
  const ref = useSR(null);

  useSE(() => {
    const fn = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', fn);
    return () => document.removeEventListener('mousedown', fn);
  }, []);

  useSE(() => {
    let active = true;
    setLoading(true);
    window._sb
      .from('eventos')
      .select('tipo, valor, session_id, created_at')
      .eq('edificio_id', building.id)
      .gte('created_at', window.clRangeStart(period))
      .order('created_at', { ascending: false })
      .limit(5000)
      .then(({ data }) => {
        if (active) { setEvents(data || []); setLoading(false); }
      });
    return () => { active = false; };
  }, [building.id, period]);

  const pLabel = window.CL_PERIODS.find(p => p.id === period).label;
  const ac = window.acHex(building.accent);

  const stats = useSM(() => {
    const visitas  = events.filter(e => e.tipo === 'vista_seccion').length;
    const sesiones = new Set(events.map(e => e.session_id)).size;

    const unitCounts = events
      .filter(e => e.tipo === 'click_unidad' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const topUnit = Object.entries(unitCounts).sort((a, b) => b[1] - a[1])[0];

    const secCounts = events
      .filter(e => e.tipo === 'vista_seccion' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const topSec = Object.entries(secCounts).sort((a, b) => b[1] - a[1])[0];

    const tourCounts = events
      .filter(e => e.tipo === 'click_360' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const top360 = Object.entries(tourCounts).sort((a, b) => b[1] - a[1])[0];

    const pisoCounts = events
      .filter(e => e.tipo === 'click_piso' && e.valor)
      .reduce((a, e) => { a[e.valor] = (a[e.valor] || 0) + 1; return a; }, {});
    const topFloor = Object.entries(pisoCounts).sort((a, b) => b[1] - a[1])[0];

    const waCount  = events.filter(e => e.tipo === 'click_whatsapp').length;
    const pdfCount = events.filter(e => e.tipo === 'click_pdf').length;
    const tourCount= events.filter(e => e.tipo === 'click_360').length;

    const tasa = visitas > 0 ? ((waCount + pdfCount) / visitas * 100).toFixed(1) + '%' : '—';

    // top unidades por vistas
    const topUnidades = Object.entries(unitCounts)
      .sort((a, b) => b[1] - a[1]).slice(0, 5)
      .map(([name, views]) => ({ name, views }));

    const SEC_LABEL = {
      unidades: 'Unidades', pisos: 'Pisos', ubicacion: 'Ubicación',
      edificio: 'Edificio', recorrido360: 'Recorrido 360°', hero: 'Inicio',
    };
    const capSec = (v) => SEC_LABEL[v] || (v ? v.charAt(0).toUpperCase() + v.slice(1) : '—');

    return {
      visitas, sesiones: sesiones || visitas,
      topUnit: topUnit ? topUnit[0] : '—',
      topSection: topSec ? capSec(topSec[0]) : '—',
      top360: top360 ? top360[0] : '—',
      topFloor: topFloor ? topFloor[0] : '—',
      tasa,
      conversions: { whatsapp: waCount, pdf: pdfCount, tour: tourCount },
      topUnidades,
    };
  }, [events]);

  // gráfico de barras
  const bars = useSM(() => {
    if (period === 'hoy') {
      const byHour = {};
      events.forEach(e => {
        const h = new Date(e.created_at).getHours();
        byHour[h] = (byHour[h] || 0) + 1;
      });
      return Array.from({ length: 24 }, (_, h) => ({
        label: h % 4 === 0 ? String(h).padStart(2, '0') : '',
        value: byHour[h] || 0,
      }));
    }
    const p = window.CL_PERIODS.find(x => x.id === period);
    const n = p ? p.days : 7;
    const pts = Math.min(n, 30);
    const byDay = {};
    events.forEach(e => { const d = e.created_at.slice(0, 10); byDay[d] = (byDay[d] || 0) + 1; });
    return Array.from({ length: pts }, (_, i) => {
      const d   = new Date(Date.now() - (pts - 1 - i) * 86400000);
      const key = d.toISOString().slice(0, 10);
      return {
        label: d.toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit' }),
        value: byDay[key] || 0,
      };
    });
  }, [events, period]);

  const everyLabel = period === 'hoy' ? 1 : bars.length > 14 ? 3 : 1;

  const maxViews = stats.topUnidades[0]?.views || 1;

  return (
    <div className="fade-in cl-page-pad" style={{ padding: 24, maxWidth: 1080, margin: '0 auto' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>
        <div>
          <window.CiKicker>Análisis</window.CiKicker>
          <div style={{ fontSize: 20, fontWeight: 700, marginTop: 5 }}>Métricas del showroom</div>
          <div style={{ fontSize: 13, color: 'var(--txt-mut)', marginTop: 4 }}>
            Cómo interactúan los compradores con {building.name}.
          </div>
        </div>

        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          {!loading && (
            <button onClick={() => printMetricas(building, pLabel, stats, bars)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              background: 'transparent', border: '1px solid var(--line)',
              borderRadius: 8, padding: '7px 13px', fontSize: 12, fontWeight: 600,
              color: 'var(--txt-mut)', cursor: 'pointer', transition: 'color .12s, border-color .12s',
            }}
              onMouseEnter={e => { e.currentTarget.style.color = 'var(--txt)'; e.currentTarget.style.borderColor = 'var(--line-strong)'; }}
              onMouseLeave={e => { e.currentTarget.style.color = 'var(--txt-mut)'; e.currentTarget.style.borderColor = 'var(--line)'; }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/><path d="M8 13h8M8 17h5"/>
              </svg>
              Descargar PDF
            </button>
          )}
          <div ref={ref} style={{ position: 'relative' }}>
          <button onClick={() => setOpen(o => !o)} style={{
            display: 'inline-flex', alignItems: 'center', gap: 10,
            background: 'var(--bg-1)', border: '1px solid var(--line)',
            borderRadius: 999, padding: '7px 14px', fontSize: 13, fontWeight: 600,
            color: 'var(--txt)', minWidth: 140,
          }}>
            <span style={{ fontSize: 11, color: 'var(--txt-mut)', fontWeight: 500 }}>Período</span>
            <span style={{ marginLeft: 'auto', display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              {pLabel}
              <span style={{ transition: 'transform .15s', transform: open ? 'rotate(180deg)' : 'none',
                display: 'grid', color: 'var(--txt-mut)' }}>
                <window.CiChevD size={14} />
              </span>
            </span>
          </button>
          {open && (
            <div className="pop" style={{
              position: 'absolute', top: 'calc(100% + 6px)', right: 0, minWidth: 180, zIndex: 40,
              background: 'var(--bg-1)', border: '1px solid var(--line-strong)', borderRadius: 'var(--r-md)',
              boxShadow: '0 16px 40px rgba(0,0,0,.55)', padding: 5,
            }}>
              {window.CL_PERIODS.map(p => {
                const active = p.id === period;
                return (
                  <button key={p.id} onClick={() => { setPeriod(p.id); setOpen(false); }} style={{
                    display: 'flex', alignItems: 'center', width: '100%', textAlign: 'left',
                    border: 'none', borderRadius: 7, padding: '9px 10px', fontSize: 13.5,
                    fontWeight: active ? 600 : 500,
                    color: active ? 'var(--txt)' : 'var(--txt-mut)',
                    background: active ? 'var(--bg-2)' : 'transparent',
                  }}
                    onMouseEnter={e => { if (!active) e.currentTarget.style.background = 'var(--bg-2)'; }}
                    onMouseLeave={e => { if (!active) e.currentTarget.style.background = 'transparent'; }}>
                    {p.label}
                    {active && <span style={{ marginLeft: 'auto', color: ac, display: 'grid' }}><window.CiCheck size={14} /></span>}
                  </button>
                );
              })}
            </div>
          )}
          </div>
        </div>
      </div>

      {loading ? (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12, padding: '60px 0', color: 'var(--txt-dim)' }}>
          <window.CiSpinner size={22} />
          <span>Cargando métricas…</span>
        </div>
      ) : (
        <>
          {/* fila 1: visitas, sesiones, tasa */}
          <div className="cl-grid3" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14, marginTop: 20 }}>
            <window.CiStatCard label="Visitas totales"   value={stats.visitas}   accent="azul" />
            <window.CiStatCard label="Sesiones únicas"   value={stats.sesiones}  accent="teal" />
            <window.CiStatCard label="Tasa de consultas" value={stats.tasa}       accent="magenta" />
          </div>
          {/* fila 2: top unit/section/360/piso */}
          <div className="cl-grid4" style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14, marginTop: 14 }}>
            <window.CiStatCard label="Unidad más vista"   value={stats.topUnit}     accent={building.accent} />
            <window.CiStatCard label="Sección más vista"  value={stats.topSection}  accent="indigo" />
            <window.CiStatCard label="360° más visto"     value={stats.top360}      accent="azul" />
            <window.CiStatCard label="Piso más visto"     value={stats.topFloor}    accent="teal" />
          </div>

          {/* gráfico + conversiones */}
          <div className="cl-chart-row" style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1fr) 280px', gap: 14, marginTop: 14, alignItems: 'start' }}>
            <window.CiCard>
              <div style={{ fontSize: 15, fontWeight: 600 }}>
                Visitas {period === 'hoy' ? 'por hora' : 'por día'}
              </div>
              <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 3, marginBottom: 6 }}>
                {period === 'hoy' ? 'Distribución horaria · hoy' : pLabel + ' · ' + bars.length + ' registros'}
              </div>
              <window.CiSeriesBars data={bars} color={ac} everyLabel={everyLabel} height={240} />
            </window.CiCard>

            <window.CiCard pad={0}>
              <div style={{ padding: '16px 18px 12px', borderBottom: '1px solid var(--line)' }}>
                <div style={{ fontSize: 15, fontWeight: 600 }}>Conversiones</div>
                <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 3 }}>Acciones de interés · {pLabel.toLowerCase()}</div>
              </div>
              <ClConvRow icon={window.CiChat} accent="teal"   label="WhatsApp"       value={stats.conversions.whatsapp} />
              <ClConvRow icon={window.CiPdf}  accent="indigo" label="Descargas PDF"  value={stats.conversions.pdf}     border />
              <ClConvRow icon={window.CiTour} accent="azul"   label="Recorrido 360°" value={stats.conversions.tour}    border />
            </window.CiCard>
          </div>

          {/* top unidades */}
          {stats.topUnidades.length > 0 && (
            <window.CiCard style={{ marginTop: 14 }} pad={0}>
              <div style={{ padding: '16px 20px 14px', borderBottom: '1px solid var(--line)' }}>
                <div style={{ fontSize: 15, fontWeight: 600 }}>Unidades más vistas</div>
                <div style={{ fontSize: 12, color: 'var(--txt-mut)', marginTop: 3 }}>Por número de clicks · {pLabel.toLowerCase()}</div>
              </div>
              <div style={{ padding: '6px 0 6px' }}>
                {stats.topUnidades.map((s, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '11px 20px',
                    borderTop: i === 0 ? 'none' : '1px solid var(--line)' }}>
                    <span className="u-mono" style={{ width: 18, fontSize: 12, fontWeight: 700,
                      color: i === 0 ? ac : 'var(--txt-dim)', flex: '0 0 auto' }}>#{i + 1}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
                        <span style={{ fontSize: 13.5, fontWeight: 600 }}>{s.name}</span>
                        <span className="u-mono" style={{ fontSize: 13, fontWeight: 700, marginLeft: 'auto', paddingLeft: 16 }}>{s.views.toLocaleString('es-AR')}</span>
                      </div>
                      <div style={{ height: 4, borderRadius: 999, background: 'var(--bg-2)' }}>
                        <div style={{
                          height: 4, borderRadius: 999,
                          background: i === 0 ? ac : window.hexA(ac, 0.45),
                          width: Math.round(s.views / maxViews * 100) + '%',
                          transition: 'width .5s cubic-bezier(.2,.7,.2,1)',
                        }} />
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </window.CiCard>
          )}
        </>
      )}
    </div>
  );
};

const ClConvRow = ({ icon: Icon, accent, label, value, border }) => {
  const c = window.acHex(accent);
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 18px',
      borderTop: border ? '1px solid var(--line)' : 'none' }}>
      <span style={{ width: 34, height: 34, borderRadius: 8, flex: '0 0 auto',
        background: window.hexA(c, 0.13), color: c, display: 'grid', placeItems: 'center' }}>
        <Icon size={17} />
      </span>
      <span style={{ flex: 1, fontSize: 13.5, fontWeight: 600 }}>{label}</span>
      <span className="u-mono" style={{ fontSize: 20, fontWeight: 700 }}>{value}</span>
    </div>
  );
};

Object.assign(window, { ClScreenLogin, ClScreenDashboard, ClScreenDisponibilidad, ClScreenMetricas });
