/* MIRAI — INBOX en tiempo real (WhatsApp / Instagram)
 *
 * Componente COMPARTIDO: la misma vista de bandeja sirve para ambos canales,
 * parametrizada por `INBOX_CFG[channel]` (título, etiqueta de contacto, ícono).
 * Así no se duplica lógica entre WhatsApp e Instagram.
 *
 * Distribución: lista compacta (pegada al sidebar) · chat protagonista (ancho) ·
 * panel de lead FIJO (sin acordeones ni scroll interno) con ficha completa +
 * "Acciones rápidas" (pausar bot, responder manual, reactivar Emma, asignar broker).
 *
 * Datos: hoy vienen de dashGetInboxConversations() (mock, ver
 * dashboard-inbox-data.jsx). El estado vive en el componente, listo para que
 * más adelante un WebSocket/fetch alimente las mismas estructuras en vivo.
 *
 * Reutiliza piezas ya definidas en dashboard.jsx (ChannelDashboardHeader,
 * DashboardSidebar, Icon, Dropdown, StatusPill, WhatsAppIcon, InstagramIcon,
 * useToast, ComingSoonNotice, COMING_SOON…) que viven en el mismo scope global.
 */

// Config visual por canal. El asistente de IA es "Emma" en ambos canales.
const INBOX_CFG = {
  whatsapp: {
    key: "whatsapp", name: "WhatsApp",
    subtitle: "Gestiona y responde conversaciones en tiempo real con Emma",
    listTitle: "Chats", contactLabel: "Teléfono",
    composerPlaceholder: "Escribe tu respuesta…",
    avatarColor: "#25D366",
  },
  instagram: {
    key: "instagram", name: "Instagram",
    subtitle: "Gestiona y responde mensajes directos en tiempo real con Emma",
    listTitle: "Mensajes", contactLabel: "Usuario",
    composerPlaceholder: "Escribe tu mensaje…",
    avatarColor: "#8134AF",
  },
  crm: {
    key: "crm", name: "CRM",
    subtitle: "Gestiona y responde consultas desde la web en tiempo real con Emma",
    listTitle: "Consultas", contactLabel: "Email",
    composerPlaceholder: "Escribe tu respuesta…",
    avatarColor: "#C0003B",
  },
};

const INBOX_FILTERS = [
  { key: "all", label: "Todos" },
  { key: "unread", label: "No leídos" },
  { key: "waiting", label: "En espera" },
];

// Estado de la atención -> clase del puntito (semántico, igual en ambos canales).
const INBOX_MODE = {
  bot:     { label: "Emma activa", dot: "is-bot" },
  waiting: { label: "En espera",   dot: "is-waiting" },
  agent:   { label: "Asesor",      dot: "is-agent" },
};

// ============ HELPERS ============
function inboxInitials(name) {
  const parts = (name || "").trim().split(/\s+/).slice(0, 2);
  return parts.map((p) => p[0] || "").join("").toUpperCase() || "?";
}
function inboxAvatarHue(name) {
  let h = 0;
  for (let i = 0; i < (name || "").length; i++) h = (h * 31 + name.charCodeAt(i)) % 360;
  return h;
}

// Clave de día (en huso horario local) para agrupar mensajes bajo el mismo
// separador — los mock no traen fecha real por mensaje, así que caen todos
// en un único grupo ("Hoy", igual que antes).
function inboxDayKey(dateStr) {
  if (!dateStr) return "mock";
  const d = new Date(dateStr);
  if (isNaN(d.getTime())) return "mock";
  return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
}

// "Hoy" / "Ayer" / "16 de julio" (con año sólo si no es el actual) — mismo
// criterio que usa WhatsApp para el separador de fecha.
function inboxDayLabel(dateStr) {
  if (!dateStr) return "Hoy";
  const d = new Date(dateStr);
  if (isNaN(d.getTime())) return "Hoy";
  const now = new Date();
  const startOfDay = (x) => new Date(x.getFullYear(), x.getMonth(), x.getDate());
  const diffDays = Math.round((startOfDay(now) - startOfDay(d)) / 86400000);
  if (diffDays === 0) return "Hoy";
  if (diffDays === 1) return "Ayer";
  const opts = { day: "numeric", month: "long" };
  if (d.getFullYear() !== now.getFullYear()) opts.year = "numeric";
  return d.toLocaleDateString("es-AR", opts);
}

// ============ AVATAR (iniciales con color fijo por canal) ============
function InboxAvatar({ name, size = 46, online = false, ring = false, bgColor }) {
  const bg = bgColor || `hsl(${inboxAvatarHue(name)} 50% 47%)`;
  return (
    <span className={`dash-ibx__avatar ${ring ? "has-ring" : ""}`} style={{ width: size, height: size }}>
      <span className="dash-ibx__avatar-circle" style={{ background: bg, fontSize: size * 0.36 }}>
        {inboxInitials(name)}
      </span>
      {online && <span className="dash-ibx__online" aria-label="En línea"></span>}
    </span>
  );
}

// ============ DROPDOWN DE ASIGNACIÓN DE BROKER (reutilizable) ============
function InboxAssign({ current, onAssign, button }) {
  return (
    <Dropdown align="left" className="dash-ibx__assign" button={button}>
      {DASH_BROKERS.map((b) => (
        <button key={b} className={`dd__opt ${current === b ? "is-sel" : ""}`} onClick={() => onAssign(b)}>{b}</button>
      ))}
    </Dropdown>
  );
}

// ============ COLUMNA IZQUIERDA: LISTA DE CHATS ============
function InboxChatList({ cfg, conversations, counts, selectedId, onSelect, search, setSearch, onTools }) {
  const filtered = conversations.filter((c) => miraiMatchesSearch(search, c.name, c.handle));
  return (
    <div className="dash-ibx__col dash-ibx__list">
      <div className="dash-ibx__list-head">
        <div className="dash-ibx__list-titlerow">
          <h3 className="dash-ibx__list-title">{cfg.listTitle}</h3>
          <span className="dash-ibx__count">{counts.all}</span>
          <div className="dash-ibx__list-tools">
            <button className="dash-ibx__toolbtn" onClick={onTools} aria-label="Opciones de la bandeja"><Icon name="sliders" size={18} /></button>
          </div>
        </div>
        <div className="dash-ibx__search">
          <Icon name="search" size={16} />
          <input type="text" value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Buscar conversaciones..." aria-label="Buscar conversaciones" />
        </div>
      </div>

      <div className="dash-ibx__items">
        {filtered.map((c) => {
          const mode = INBOX_MODE[c.mode] || INBOX_MODE.bot;
          const last = c.messages[c.messages.length - 1];
          const lastText = last ? (last.from === "emma" ? "Emma: " : last.from === "agent" ? "Asesor: " : "") + last.text : "";
          return (
            <button key={c.id} className={`dash-ibx__item ${selectedId === c.id ? "is-active" : ""}`} onClick={() => onSelect(c.id)}>
              <InboxAvatar name={c.name} online={c.online} ring={cfg.key === "instagram"} bgColor={cfg.avatarColor || "#25D366"} />
              <span className="dash-ibx__item-body">
                <span className="dash-ibx__item-top">
                  <span className="dash-ibx__item-name">{c.name}</span>
                  <span className="dash-ibx__item-time">{c.lastTime}</span>
                </span>
                <span className="dash-ibx__item-bottom">
                  <span className="dash-ibx__item-last">{lastText}</span>
                  <span className="dash-ibx__item-right">
                    {c.unread > 0 && <span className="dash-ibx__badge">{c.unread}</span>}
                    <span className={`dash-ibx__dot ${mode.dot}`} title={mode.label}></span>
                  </span>
                </span>
              </span>
            </button>
          );
        })}
        {filtered.length === 0 && <div className="dash-ibx__empty-list">No hay conversaciones para este filtro.</div>}
      </div>

      <div className="dash-ibx__list-foot"><span className="dash-ibx__live"></span>Actualizado en tiempo real</div>
    </div>
  );
}

// ============ COLUMNA CENTRAL: CONVERSACIÓN ============
// Header limpio (solo nombre + estado). Las acciones del bot viven en el panel
// derecho ("Acciones rápidas"), no sobre el nombre del contacto.
function InboxConversation({ cfg, conv, onSend, onBack, hideComposer }) {
  const [draft, setDraft] = React.useState("");
  const inputRef = React.useRef(null);
  const bodyRef = React.useRef(null);
  const paused = conv && conv.mode === "agent";

  React.useEffect(() => {
    if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
  }, [conv && conv.id, conv && conv.messages.length]);
  React.useEffect(() => {
    if (paused && inputRef.current) inputRef.current.focus();
  }, [paused, conv && conv.id]);
  React.useEffect(() => { setDraft(""); }, [conv && conv.id]);

  if (!conv) {
    return (
      <div className="dash-ibx__col dash-ibx__conv dash-ibx__conv--empty">
        <span className="dash-ibx__conv-emptyicon"><Icon name="inbox" size={30} /></span>
        <p>Elegí una conversación para verla acá.</p>
      </div>
    );
  }

  const submit = () => {
    const text = draft.trim();
    if (!text) return;
    onSend(conv.id, text);
    setDraft("");
  };
  const onKey = (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); submit(); } };

  return (
    <div className="dash-ibx__col dash-ibx__conv">
      <header className="dash-ibx__conv-head">
        <button className="dash-ibx__back" onClick={onBack} aria-label="Volver a la lista"><Icon name="chevron" size={20} /></button>
        <InboxAvatar name={conv.name} size={44} online={conv.online} ring={cfg.key === "instagram"} bgColor={cfg.avatarColor || "#25D366"} />
        <div className="dash-ibx__conv-id">
          <span className="dash-ibx__conv-name">{conv.name}</span>
          <span className="dash-ibx__conv-sub">
            <span className="dash-ibx__conv-handle">{conv.source || conv.handle}</span>
          </span>
        </div>
      </header>

      {paused && (
        <div className="dash-ibx__takeover" role="status">
          <span className="dash-ibx__pausebars"><i></i><i></i></span>
          <b>Bot pausado</b> · respondiendo asesor
        </div>
      )}

      <div className={`dash-ibx__msgs dash-ibx__msgs--${cfg.key}`} ref={bodyRef}>
        {(() => {
          let lastDayKey = null;
          return conv.messages.map((m, i) => {
            const sent = m.from !== "lead";
            const dayKey = inboxDayKey(m.date);
            const showDateChip = dayKey !== lastDayKey;
            lastDayKey = dayKey;
            if (m.from === "event") {
              return (
                <React.Fragment key={i}>
                  {showDateChip && <span className="dash-ibx__datechip">{inboxDayLabel(m.date)}</span>}
                  <div className="dash-ibx__event">
                    <Icon name="info" size={13} />
                    <span>{m.text}</span>
                    {m.time && <span className="dash-ibx__event-time">{m.time}</span>}
                  </div>
                </React.Fragment>
              );
            }
            return (
              <React.Fragment key={i}>
                {showDateChip && <span className="dash-ibx__datechip">{inboxDayLabel(m.date)}</span>}
                <div className={`dash-ibx__msg is-${m.from}`}>
                  {m.from === "emma" && <span className="dash-ibx__sender">Emma</span>}
                  {m.from === "agent" && <span className="dash-ibx__sender">Asesor</span>}
                  <div className="dash-ibx__bubble">
                    <span className="dash-ibx__btext">{m.text}</span>
                    <span className="dash-ibx__bmeta">{m.time}{sent && <Icon name="check2" size={15} />}</span>
                  </div>
                </div>
              </React.Fragment>
            );
          });
        })()}
      </div>

      {!hideComposer && (
        <div className="dash-ibx__composer">
          <div className="dash-ibx__inputwrap">
            <button className="dash-ibx__composer-icon" type="button" aria-label="Emoji"><Icon name="smile" size={20} /></button>
            <textarea
              ref={inputRef} rows={1} value={draft}
              onChange={(e) => setDraft(e.target.value)} onKeyDown={onKey}
              placeholder={cfg.composerPlaceholder} className="dash-ibx__input" />
            <button className="dash-ibx__composer-icon" type="button" aria-label="Adjuntar"><Icon name="clip" size={19} /></button>
          </div>
          <button className="dash-ibx__send" onClick={submit} disabled={!draft.trim()} aria-label="Enviar mensaje"><Icon name="send" size={20} /></button>
        </div>
      )}
    </div>
  );
}

// ============ COLUMNA DERECHA: DETALLE DEL LEAD (fijo, sin acordeones) ============
function InboxKV({ k, children, wide }) {
  return (
    <div className={`dash-ibx__kv ${wide ? "is-wide" : ""}`}>
      <span className="dash-ibx__kv-k">{k}</span>
      <span className="dash-ibx__kv-v">{children}</span>
    </div>
  );
}

function InboxLeadPanel({ cfg, conv, onPause, onTakeOver, onReactivate, onAssignBroker, onClose, onComingSoon, onToast, hideQuickActions }) {
  const [showDiagnosis, setShowDiagnosis] = React.useState(false);
  React.useEffect(() => { setShowDiagnosis(false); }, [conv && conv.id]);

  if (!conv) return null;
  const d = conv.lead;
  const paused = conv.mode === "agent";
  const operatorLabel = (d.derivedTo && d.derivedTo.length) ? d.derivedTo.join(", ") : (d.broker && d.broker !== "Sin asignar" ? d.broker : "");
  const diagnosisText = d.diagnosis && miraiFormatDiagnosis({
    name: conv.name, operator: operatorLabel, phone: conv.handle, intent: d.intent, summary: d.diagnosis,
  });

  const copyDiagnosis = async () => {
    if (!diagnosisText) return;
    try {
      await navigator.clipboard.writeText(diagnosisText);
    } catch (e) { /* clipboard no disponible, igual mostramos el texto */ }
    setShowDiagnosis(true);
    if (onToast) onToast("Diagnóstico copiado");
  };

  return (
    <div className="dash-ibx__rail">
      {/* Detalles del lead — todo visible, sin desplegables; crece para llenar el alto */}
      <div className="dash-ibx__card dash-ibx__card--grow">
        <header className="dash-ibx__lead-head">
          <h3 className="dash-ibx__lead-title">Detalles del lead</h3>
          <button className="dash-iconbtn dash-ibx__lead-close" onClick={onClose} aria-label="Cerrar detalle"><Icon name="close" size={16} /></button>
        </header>
        <div className="dash-ibx__lead-body">
          <div className="dash-ibx__lead-grid">
            <InboxKV k="Nombre">{conv.name}</InboxKV>
            <InboxKV k={cfg.contactLabel}>{conv.handle}</InboxKV>
            {d.operation && <InboxKV k="Operación">{d.operation}</InboxKV>}
            {d.propertyType && <InboxKV k="Tipo de propiedad">{d.propertyType}</InboxKV>}
            {d.intent && <InboxKV k="Intención">{d.intent}</InboxKV>}
            {d.zone && <InboxKV k="Zona de interés">{d.zone}</InboxKV>}
            {d.budget && <InboxKV k="Presupuesto">{d.budget}</InboxKV>}
            {d.status && <InboxKV k="Estado"><StatusPill status={d.status} /></InboxKV>}
            {d.broker && <InboxKV k="Broker asignado">{d.broker}</InboxKV>}
            {d.origin && <InboxKV k="Origen del lead">{d.origin}</InboxKV>}
            {d.createdAt && <InboxKV k="Fecha de ingreso">{d.createdAt}</InboxKV>}
            {d.lastContact && <InboxKV k="Último contacto">{d.lastContact}</InboxKV>}
            {d.propertyOfInterest && <InboxKV k="Propiedad de interés" wide>{d.propertyOfInterest}</InboxKV>}
          </div>

          {d.tags && d.tags.length > 0 && (
            <div className="dash-ibx__lead-block">
              <span className="dash-ibx__lead-label">Etiquetas</span>
              <div className="dash-ibx__tags">
                {d.tags.map((t) => <span key={t} className="dash-ibx__tag">{t}</span>)}
                <button className="dash-ibx__tag dash-ibx__tag--add" onClick={onComingSoon} aria-label="Agregar etiqueta"><Icon name="plus" size={13} /></button>
              </div>
            </div>
          )}

          {d.notes && (
            <div className="dash-ibx__lead-block">
              <span className="dash-ibx__lead-label">Notas</span>
              <p className="dash-ibx__notes">{d.notes}</p>
            </div>
          )}

          {d.diagnosis && (
            <div className="dash-ibx__lead-block">
              <button type="button" className="dash-ibx__btn dash-ibx__btn--diagnosis dash-ibx__btn--block" onClick={copyDiagnosis}>
                <Icon name="copy" size={15} /> Copiar diagnóstico
              </button>
              {showDiagnosis && (
                <div className="dash-ibx__diagnosis" role="status">
                  <span className="dash-ibx__diagnosis-flag"><Icon name="check2" size={13} /> Diagnóstico copiado</span>
                  <p className="dash-ibx__diagnosis-text">{diagnosisText}</p>
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {/* Acciones rápidas — fijo, contextual al estado del bot */}
      {!hideQuickActions && (
        <div className="dash-ibx__card">
          <div className="dash-ibx__card-head">
            <h3 className="dash-ibx__card-title">Acciones rápidas</h3>
            <span className={`dash-ibx__statechip ${paused ? "is-agent" : "is-bot"}`}>
              <span className={`dash-ibx__dot ${paused ? "is-agent" : "is-bot"}`}></span>
              {paused ? "Bot pausado" : "Emma activa"}
            </span>
          </div>
          <div className="dash-ibx__actions">
            {paused ? (
              <button className="dash-ibx__btn dash-ibx__btn--accent dash-ibx__btn--block" onClick={() => onReactivate(conv.id)}>
                <Icon name="play" size={15} /> Reactivar Emma
              </button>
            ) : !cfg.hideManualBtn ? (
              <button className="dash-ibx__btn dash-ibx__btn--accent dash-ibx__btn--block" onClick={() => onTakeOver(conv.id)}>
                <Icon name="user" size={16} /> Responder manualmente
              </button>
            ) : null}
          </div>
        </div>
      )}
    </div>
  );
}

// Convierte un lead de la API (/dashboard/chats) al shape que espera InboxChatList.
function apiChatToConversation(c) {
  return {
    id: c.phone,
    name: c.nombre,
    handle: c.phone,
    avatar: null,
    mode: "bot",
    unread: 0,
    online: false,
    lastTime: c.fecha_ultimo_contacto ? c.fecha_ultimo_contacto.slice(-5) : "",
    messages: [],
    lead: {
      intent: c.intencion,
      operation: c.operacion,
      zone: c.zona,
      budget: c.presupuesto,
      propertyType: c.tipo_propiedad,
      status: c.estado,
      lastContact: c.fecha_ultimo_contacto,
      diagnosis: c.resumen,
      derivedTo: Array.isArray(c.derivado_a) ? c.derivado_a : [],
    },
  };
}

// Navegación cruzada desde el Tablero: "Ir a la conversación" guarda acá qué
// chat abrir, la página de Inbox lo lee (y borra) al montar — el router de
// hash de la app no soporta query params, así que no podemos mandarlo en la URL.
const MIRAI_OPEN_CHAT_KEY = "mirai_open_chat";
function mirai_setPendingChat(channel, id) {
  try { sessionStorage.setItem(MIRAI_OPEN_CHAT_KEY, JSON.stringify({ channel, id })); } catch (e) {}
}
function mirai_consumePendingChat(channel) {
  try {
    const raw = sessionStorage.getItem(MIRAI_OPEN_CHAT_KEY);
    if (!raw) return null;
    const { channel: pendingChannel, id } = JSON.parse(raw);
    if (pendingChannel !== channel) return null;
    sessionStorage.removeItem(MIRAI_OPEN_CHAT_KEY);
    return id || null;
  } catch (e) { return null; }
}

// ============ PÁGINA DE INBOX (orquestador) ============
function ChannelInboxPage({ channel, user, onLogout, env, setEnv, showEnvSwitch }) {
  const cfg = INBOX_CFG[channel];
  const headerCfg = { ...dashGetChannelCfg(channel), subtitle: cfg.subtitle };

  // Cuentas live solo consumen datos reales en WhatsApp: nunca sembrar con mock.
  const isLiveUser = MIRAI_LIVE_USERS.has((user || "").toLowerCase());
  const liveWhatsApp = isLiveUser && channel === "whatsapp";

  // Si venimos del Tablero con "Ir a la conversación", abrimos ese chat puntual
  // en lugar del primero de la lista (una sola vez: se consume y se borra al montar).
  const [pendingChat] = React.useState(() => mirai_consumePendingChat(channel));

  const [conversations, setConversations] = React.useState(() => (liveWhatsApp ? [] : dashGetInboxConversations(channel)));
  const [selectedId, setSelectedId] = React.useState(() => {
    if (liveWhatsApp) return pendingChat || null;
    const list = dashGetInboxConversations(channel);
    if (pendingChat && list.some((c) => c.id === pendingChat)) return pendingChat;
    return list.length ? list[0].id : null;
  });
  const [search, setSearch] = React.useState("");
  const [showLead, setShowLead] = React.useState(true);
  const [sbOpen, setSbOpen] = React.useState(false);
  const [filters, setFilters] = React.useState({ period: "30d", channel, compare: false });
  const [lastUpdated, setLastUpdated] = React.useState(() => new Date());
  const [toast, showToast] = useToast();

  // Datos en vivo (solo WhatsApp + usuarios live)
  const { chats: liveChats, loading: chatsLoading, isLive: inboxIsLive, refresh: refreshChats } = useInboxChats(user, env);

  // Sincronizar lista de conversaciones con la API cuando hay datos en vivo.
  // Corre siempre que sea WhatsApp+live, incluso con 0 chats (para no dejar
  // el sembrado mock inicial ni datos viejos si la lista real quedó vacía).
  React.useEffect(() => {
    if (!liveWhatsApp) return;
    // /dashboard/chats trae una fila por CONSULTA (un mismo contacto puede
    // tener varias, ver dashboard-tablero.jsx) — acá dedupe por teléfono:
    // el Inbox es un hilo de conversación por contacto, no por consulta.
    // Ya viene ordenado por fecha desc, así que nos quedamos con la primera
    // aparición (la más reciente) de cada teléfono.
    const seenPhones = new Set();
    const deduped = liveChats.filter((c) => {
      if (seenPhones.has(c.phone)) return false;
      seenPhones.add(c.phone);
      return true;
    });
    const converted = deduped.map(apiChatToConversation);
    setConversations(converted);
    setSelectedId((prev) => {
      // Todavía no llegó el primer fetch (converted vacío mientras carga):
      // no pisar una selección pendiente (ej. "Ir a la conversación" desde
      // el Tablero) con una lista vacía transitoria.
      if (!converted.length && chatsLoading) return prev;
      return prev && converted.some((c) => c.id === prev) ? prev : (converted[0] ? converted[0].id : null);
    });
    setLastUpdated(new Date());
  }, [liveChats, liveWhatsApp, chatsLoading]);

  const selected = conversations.find((c) => c.id === selectedId) || null;

  // Mensajes del chat seleccionado desde Supabase (solo en vivo)
  const { messages: liveMessages } = useInboxMessages(user, liveWhatsApp ? selected?.handle : null, env);

  // Conversación efectiva: reemplaza mensajes con los reales de Supabase cuando corresponde.
  const effectiveSelected = React.useMemo(() => {
    if (!liveWhatsApp || !selected || !liveMessages.length) return selected;
    return {
      ...selected,
      messages: liveMessages.map((m) => {
        if (m.kind === "event") {
          return { from: "event", text: m.text, time: m.created_at ? miraiFmtTime(new Date(m.created_at)) : "", date: m.created_at };
        }
        return {
          from: m.role === "user" ? "lead" : "emma",
          text: typeof m.content === "string" ? m.content : JSON.stringify(m.content),
          time: m.created_at ? miraiFmtTime(new Date(m.created_at)) : "",
          date: m.created_at,
        };
      }),
    };
  }, [selected, liveMessages, liveWhatsApp]);

  const counts = {
    all: conversations.length,
    unread: conversations.filter((c) => c.unread > 0).length,
    waiting: conversations.filter((c) => c.mode === "waiting").length,
  };

  const patchConv = (id, fn) => setConversations((cs) => cs.map((c) => (c.id === id ? fn(c) : c)));
  const onSelect = (id) => { setSelectedId(id); patchConv(id, (c) => ({ ...c, unread: 0 })); };
  const onPause = (id) => patchConv(id, (c) => ({ ...c, mode: "agent" }));
  const onReactivate = (id) => patchConv(id, (c) => ({ ...c, mode: "bot" }));
  const onTakeOver = (id) => { setShowLead(true); patchConv(id, (c) => ({ ...c, mode: "agent" })); };
  const onSend = (id, text) =>
    patchConv(id, (c) => ({ ...c, mode: "agent", messages: [...c.messages, { from: "agent", text, time: miraiFmtTime(new Date()) }] }));
  const onAssignBroker = (id, broker) => {
    patchConv(id, (c) => ({ ...c, lead: { ...c.lead, broker } }));
    showToast(broker === "Sin asignar" ? "Broker desasignado" : `Asignado a ${broker}`);
  };
  const onRefresh = () => {
    if (liveWhatsApp) { refreshChats(); }
    else { setConversations(dashGetInboxConversations(channel)); }
    setLastUpdated(new Date());
  };

  return (
    <div className="dboard">
      <DashboardSidebar active={channel} user={user} onComingSoon={() => showToast(COMING_SOON)} open={sbOpen} onClose={() => setSbOpen(false)} />

      <div className="dash-main dash-main--inbox">
        <ChannelDashboardHeader
          cfg={headerCfg} filters={filters} setFilters={setFilters}
          onLogout={onLogout} onMenu={() => setSbOpen(true)} onAccount={() => showToast(COMING_SOON)}
          onRefresh={onRefresh} loading={chatsLoading} lastUpdated={lastUpdated}
          env={env} setEnv={setEnv} showEnvSwitch={showEnvSwitch} />

        <div className={`dash-inbox is-${channel} ${selectedId ? "has-selection" : ""} ${showLead ? "" : "hide-lead"}`}>
          <InboxChatList
            cfg={cfg} conversations={conversations} counts={counts} selectedId={selectedId} onSelect={onSelect}
            search={search} setSearch={setSearch}
            onTools={() => showToast(COMING_SOON)} />

          <InboxConversation cfg={cfg} conv={effectiveSelected} onSend={onSend} onBack={() => setSelectedId(null)} hideComposer={inboxIsLive} />

          {showLead && (
            <InboxLeadPanel
              cfg={cfg} conv={effectiveSelected}
              onPause={onPause} onTakeOver={onTakeOver} onReactivate={onReactivate} onAssignBroker={onAssignBroker}
              onClose={() => setShowLead(false)} onComingSoon={() => showToast(COMING_SOON)} onToast={showToast}
              hideQuickActions={inboxIsLive} />
          )}
        </div>
      </div>

      <ComingSoonNotice msg={toast} />
    </div>
  );
}

Object.assign(window, { ChannelInboxPage, INBOX_CFG, mirai_setPendingChat });
