// ═══════════════════════════════════════════════════════
// BAUKO CRM v2 — Agenda (calendário comercial)
// ═══════════════════════════════════════════════════════
/* global React, CRM_DATA, CRM_API, Panel, Modal, FormField, fDate, fDateTime */
const { useState: useAgState, useMemo: useAgMemo, useEffect: useAgEffect } = React;

const TIPO_ICON  = { visita:"map-pin", reuniao:"users", ligacao:"phone", followup:"clock", email:"mail", whatsapp:"message-circle" };
const TIPO_COLOR = { visita:"#3370b7", reuniao:"#2e8b57", ligacao:"#007c44", followup:"#f4a300", email:"#706f6f", whatsapp:"#25d366" };
const TIPO_LABEL = { visita:"Visita", reuniao:"Reunião", ligacao:"Ligação", followup:"Follow-up", email:"E-mail", whatsapp:"WhatsApp" };
const TIPO_TIPOS = ["visita","reuniao","ligacao","followup","email","whatsapp"];

// ── Justificativas de visita planejada ──────────────────────────────────────
// Justificativas de cancelamento de visita planejada
var JUSTIF_CANCELAR = [
  { cat:'reagendamento',   label:'Cliente solicitou reagendamento' },
  { cat:'conflito',        label:'Conflito de agenda do vendedor' },
  { cat:'logistica',       label:'Logística / distância inviável' },
  { cat:'indisponivel',    label:'Cliente indisponível no dia' },
  { cat:'cliente_ausente', label:'Cliente ausente / não recebeu' },
  { cat:'cliente_ocupado', label:'Cliente não tinha tempo' },
  { cat:'outros',          label:'Outros' },
];
var _AG_CADENCIA = { 'Grande conta':7, 'A':14, 'B':30, 'C':60, 'D':null };
function _agCalcProxima(classe, baseIso) {
  var dias = _AG_CADENCIA[classe];
  if (!dias) return null;
  var base = baseIso ? new Date(baseIso) : new Date();
  base.setDate(base.getDate() + dias);
  return base.toISOString().slice(0, 10);
}

// ── Outlook status helpers ───────────────────────────────────────────────────
function _agHasOutlook(id) { return typeof CRM_API !== 'undefined' && CRM_API.hasOutlookEvent(id); }

// ── Componente principal ─────────────────────────────────────────────────────
function Agenda({ onNav }) {
  var [tipoFilter,    setTipoFilter]    = useAgState("todos");
  var [periodoFilter, setPeriodoFilter] = useAgState("todos");
  var [weekOffset,    setWeekOffset]    = useAgState(0);
  var [showEditModal, setShowEditModal] = useAgState(false);
  var [editEvt,       setEditEvt]       = useAgState(null);
  var [saving,        setSaving]        = useAgState(false);
  var [syncing,       setSyncing]       = useAgState(false);
  var [tick,          setTick]          = useAgState(0);
  var [showPlanejador,  setShowPlanejador]  = useAgState(false);
  var [showJustif,      setShowJustif]      = useAgState(false);
  var [justifEvt,       setJustifEvt]       = useAgState(null);

  // Campos do form de edição
  var [eTipo,   setETipo]   = useAgState("ligacao");
  var [eTitulo, setETitulo] = useAgState("");
  var [eData,   setEData]   = useAgState("");
  var [eDur,    setEDur]    = useAgState("");
  var [eLocal,  setELocal]  = useAgState("");
  var [eOpId,   setEOpId]   = useAgState("");
  var [eVendId, setEVendId] = useAgState("");

  // ── Visibilidade por papel (CRM_USER) ────────────────────────
  // Comercial só vê próprios eventos; BDR/Admin/Gerente veem todos.
  var _agPodeVerTodos = !!(window.CRM_USER && window.CRM_USER.podeVerOpAlheia);
  var _agMeuUserId    = (window.CRM_USER && window.CRM_USER.userId) || null;
  var _agMeuEmail     = ((window.CRM_USER && window.CRM_USER.email) || '').toLowerCase();
  var eventosTodos    = CRM_DATA.agenda || [];
  var eventos = _agPodeVerTodos
    ? eventosTodos
    : eventosTodos.filter(function(ev) {
        // vendedor_id pode estar como U-id OU como email (legacy)
        return ev.vendedor_id === _agMeuUserId || (ev.vendedor_id && ev.vendedor_id.toLowerCase && ev.vendedor_id.toLowerCase() === _agMeuEmail);
      });
  var usuarios  = CRM_DATA.usuarios || [];

  // ── Semana ───────────────────────────────────────────────────────────────
  var weekStart = useAgMemo(function() {
    var d = new Date();
    d.setHours(0, 0, 0, 0);
    d.setDate(d.getDate() - ((d.getDay() + 6) % 7) + weekOffset * 7);
    return d;
  }, [weekOffset]);

  var weekEnd = useAgMemo(function() {
    var d = new Date(weekStart); d.setDate(d.getDate() + 6); d.setHours(23, 59, 59, 999); return d;
  }, [weekStart]);

  var weekDays = useAgMemo(function() {
    var out = [];
    for (var i = 0; i < 7; i++) { var d = new Date(weekStart); d.setDate(d.getDate() + i); out.push(d); }
    return out;
  }, [weekStart]);

  var weekLabel = useAgMemo(function() {
    var opt = { day:'2-digit', month:'long' };
    return weekStart.toLocaleDateString('pt-BR', opt) + ' a ' + weekEnd.toLocaleDateString('pt-BR', opt) + ' · ' + weekStart.getFullYear();
  }, [weekStart, weekEnd]);

  // ── Filtro da lista ──────────────────────────────────────────────────────
  var filtered = useAgMemo(function() {
    var ev = eventos.slice();
    if (periodoFilter === "planejadas") {
      ev = ev.filter(function(e) { return e.origem === 'planejador'; });
    } else {
      if (tipoFilter !== "todos") ev = ev.filter(function(e) { return e.tipo === tipoFilter; });
      if (periodoFilter === "hoje") {
        var hoje = new Date().toISOString().slice(0, 10);
        ev = ev.filter(function(e) { return (e.data || '').slice(0, 10) === hoje; });
      } else if (periodoFilter === "semana") {
        ev = ev.filter(function(e) { var d = new Date(e.data); return d >= weekStart && d <= weekEnd; });
      } else if (periodoFilter === "mes") {
        var y = new Date().getFullYear(), m = new Date().getMonth();
        ev = ev.filter(function(e) { var d = new Date(e.data); return d.getFullYear() === y && d.getMonth() === m; });
      }
    }
    return ev.sort(function(a, b) { return new Date(a.data) - new Date(b.data); });
  }, [eventos, tipoFilter, periodoFilter, weekStart, weekEnd, tick]);

  // ── KPIs da semana ───────────────────────────────────────────────────────
  var kpiSemana = useAgMemo(function() {
    return eventos.filter(function(e) { var d = new Date(e.data); return d >= weekStart && d <= weekEnd; });
  }, [eventos, weekStart, weekEnd, tick]);

  // ── Planejadas pendentes (passado, sem status) ───────────────────────────
  var planejPendentes = useAgMemo(function() {
    var hj = new Date(); hj.setHours(0,0,0,0);
    return eventos.filter(function(e) {
      return e.origem === 'planejador' && !e.status_visita && new Date(e.data) < hj;
    }).length;
  }, [eventos, tick]);

  // ── Agrupamento por data ─────────────────────────────────────────────────
  var groups = useAgMemo(function() {
    var map = new Map();
    filtered.forEach(function(e) {
      var day = (e.data || '').slice(0, 10);
      if (!map.has(day)) map.set(day, []);
      map.get(day).push(e);
    });
    return Array.from(map.entries()).sort(function(a, b) { return a[0].localeCompare(b[0]); });
  }, [filtered]);

  // ── Oportunidades do evento editado ──────────────────────────────────────
  var opsDoEvt = useAgMemo(function() {
    if (!editEvt || !editEvt.cliente_id) return [];
    return (CRM_DATA.oportunidades || []).filter(function(o) {
      return o.cliente_id === editEvt.cliente_id && !o.cancelada_em;
    });
  }, [editEvt]);

  // ── Abrir modal ──────────────────────────────────────────────────────────
  function abrirEditar(evt) {
    setEditEvt(evt);
    setETipo(evt.tipo || 'ligacao');
    setETitulo(evt.titulo || '');
    var dtLocal = '';
    if (evt.data) {
      var d = new Date(evt.data);
      var pad = function(n) { return String(n).padStart(2, '0'); };
      dtLocal = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + 'T' + pad(d.getHours()) + ':' + pad(d.getMinutes());
    }
    setEData(dtLocal);
    setEDur(evt.duracao || '');
    setELocal(evt.local || '');
    setEOpId(evt.op_id || '');
    setEVendId(evt.vendedor_id || '');
    setShowEditModal(true);
  }

  function fecharEditar() { setShowEditModal(false); setSaving(false); setSyncing(false); }

  // ── Salvar edição ────────────────────────────────────────────────────────
  async function salvarEdicao() {
    if (!eTitulo.trim()) { window.CRM_TOAST('Informe o título do compromisso.', 'warn'); return; }
    if (!eData)          { window.CRM_TOAST('Informe a data e hora.', 'warn'); return; }
    setSaving(true);
    try {
      var campos = {
        tipo: eTipo, titulo: eTitulo.trim(),
        data: new Date(eData).toISOString(),
        duracao: eDur || '', local: eLocal || '',
        op_id: eOpId || '', vendedor_id: eVendId || ''
      };
      Object.assign(editEvt, campos);
      if (typeof CRM_API !== 'undefined' && editEvt._spId) {
        CRM_API.updateItem('Agenda', editEvt._spId, campos)
          .catch(function(e) { console.warn('[CRM] agenda update:', e.message); });
      }
      // Sincronizar com Outlook
      setSyncing(true);
      if (typeof CRM_API !== 'undefined') {
        await CRM_API.criarEventoOutlook(editEvt);
      }
      setSyncing(false);
      var temOutlook = _agHasOutlook(editEvt.id);
      fecharEditar();
      setTick(function(t) { return t + 1; });
      if (typeof window.showCrmToast === 'function') {
        window.showCrmToast('Compromisso atualizado' + (temOutlook ? ' · Outlook ✓' : ''), 'ok');
      }
    } catch(e) {
      window.CRM_TOAST('Erro ao salvar: ' + e.message, 'error');
      setSaving(false); setSyncing(false);
    }
  }

  // ── Handlers visita planejada ────────────────────────────────────────────
  function abrirJustif(evt) {
    setJustifEvt(evt);
    setShowJustif(true);
  }
  function fecharJustif() { setShowJustif(false); setJustifEvt(null); }

  function _onJustifSalva() {
    setTick(function(t) { return t + 1; });
    if (typeof window.showCrmToast === 'function') window.showCrmToast('Visita cancelada.', 'ok');
  }

  function _abrirAtividadeModal(evt) {
    if (typeof window.CRM_OPEN_ATIVIDADE !== 'function') {
      if (typeof window.showCrmToast === 'function') window.showCrmToast('Modal de atividade indisponível.', 'warn');
      return;
    }
    var cli = CRM_DATA.getCliente ? CRM_DATA.getCliente(evt.cliente_id) : null;
    window.CRM_OPEN_ATIVIDADE({
      clienteId:    evt.cliente_id  || '',
      clienteNome:  cli ? cli.razao : '',
      tipo:         evt.tipo        || 'visita',
      titulo:       evt.titulo      || '',
      data:         evt.data        || '',
      vendedorId:   evt.vendedor_id || '',
      opId:         evt.op_id       || '',
      agendaEvtRef: evt,
      onSalvo:      function() { setTick(function(t){ return t + 1; }); },
    });
  }

  // ── Excluir evento ───────────────────────────────────────────────────────
  async function excluirEvento(evt) {
    if (!await window.CRM_CONFIRM('Excluir "' + evt.titulo + '"?\nO evento também será removido do Outlook, se sincronizado.', { danger: true })) return;
    // Remove de CRM_DATA.agenda (fonte de verdade) — não do array filtrado "eventos"
    var _agIdx = CRM_DATA.agenda.indexOf(evt);
    if (_agIdx !== -1) CRM_DATA.agenda.splice(_agIdx, 1);
    if (typeof CRM_API !== 'undefined') {
      if (evt._spId) CRM_API.deleteItem('Agenda', evt._spId).catch(function(e) { console.warn('[CRM] agenda delete:', e.message); });
      CRM_API.excluirEventoOutlook(evt.id).catch(function(e) { console.warn('[CRM] excluirEventoOutlook:', e.message); });
    }
    setShowEditModal(false);
    setTick(function(t) { return t + 1; });
    if (typeof window.showCrmToast === 'function') window.showCrmToast('Compromisso excluído', 'ok');
  }

  var tipos = ["todos","visita","reuniao","ligacao","followup","email","whatsapp"];
  var hoje = new Date().toISOString().slice(0, 10);

  return (
    <div data-screen-label="07 Agenda">

      {/* ── KPIs ─────────────────────────────────────── */}
      <div className="kpi-grid" style={{ gridTemplateColumns:"repeat(4,1fr)", marginBottom:18 }}>
        <KpiAg eyebrow="Esta semana"         valor={kpiSemana.length} icon="calendar-days" cor="var(--grn)" />
        <KpiAg eyebrow="Visitas"             valor={kpiSemana.filter(function(e){return e.tipo==="visita";}).length} icon="map-pin" cor="var(--info)" />
        <KpiAg eyebrow="Reuniões"            valor={kpiSemana.filter(function(e){return e.tipo==="reuniao";}).length} icon="users" cor="var(--ok)" />
        <KpiAg eyebrow="Ligações/Follow-ups" valor={kpiSemana.filter(function(e){return e.tipo==="ligacao"||e.tipo==="followup";}).length} icon="phone-call" cor="var(--warn)" />
      </div>

      {/* ── Week strip ───────────────────────────────── */}
      <Panel title={"Semana de " + weekLabel} actions={
        <div style={{ display:"flex", gap:6, alignItems:"center" }}>
          <button className="btn btn-primary" style={{ padding:"6px 12px", fontSize:12 }}
            onClick={function(){ setShowPlanejador(true); }}>
            <i data-lucide="calendar-plus" style={{ width:13, height:13 }}></i> Planejar semana
          </button>
          <button className="btn btn-secondary" style={{ padding:"6px 10px" }}
            onClick={function(){ setWeekOffset(function(w){ return w-1; }); }}>
            <i data-lucide="chevron-left" style={{ width:14, height:14 }}></i>
          </button>
          <button className="btn btn-secondary" style={{ padding:"6px 10px" }}
            onClick={function(){ setWeekOffset(0); }}>Hoje</button>
          <button className="btn btn-secondary" style={{ padding:"6px 10px" }}
            onClick={function(){ setWeekOffset(function(w){ return w+1; }); }}>
            <i data-lucide="chevron-right" style={{ width:14, height:14 }}></i>
          </button>
        </div>
      } noPad>
        <div style={{ display:"grid", gridTemplateColumns:"repeat(7,1fr)", gap:0, padding:14 }}>
          {weekDays.map(function(d, i) {
            var dayKey  = d.toISOString().slice(0, 10);
            var dayEvts = eventos.filter(function(e){ return (e.data||'').slice(0,10) === dayKey; });
            var dayName = d.toLocaleDateString("pt-BR",{ weekday:"short" }).replace(".","");
            var isWeekend = i >= 5;
            var isToday   = dayKey === hoje;
            return (
              <div key={i} style={{
                borderRight: i < 6 ? "1px solid var(--border)" : "none",
                padding:"8px 8px 14px", minHeight:160,
                background: isWeekend ? "var(--surface-2)" : "transparent",
                opacity: isWeekend ? 0.65 : 1,
              }}>
                <div style={{ marginBottom:10 }}>
                  <div style={{ font:"600 9px/1 var(--ff-body)", textTransform:"uppercase", letterSpacing:".1em", color:"var(--tx-3)" }}>
                    {dayName}
                  </div>
                  <div style={{ font:"400 24px/1 var(--ff-display)", letterSpacing:".02em",
                    color: isToday ? "var(--grn)" : "var(--tx)",
                    fontWeight: isToday ? 700 : 400, marginTop:4 }}>
                    {String(d.getDate()).padStart(2,"0")}
                  </div>
                  {isToday && <div style={{ width:4, height:4, borderRadius:"50%", background:"var(--grn)", margin:"3px auto 0" }}></div>}
                </div>
                <div style={{ display:"flex", flexDirection:"column", gap:5 }}>
                  {dayEvts.map(function(e) {
                    return <MiniEvent key={e.id} evt={e} onEdit={function(){ abrirEditar(e); }} />;
                  })}
                </div>
              </div>
            );
          })}
        </div>
      </Panel>

      <div style={{ height:14 }}></div>

      {/* ── Lista detalhada ──────────────────────────── */}
      <Panel title="Próximos compromissos" meta={filtered.length + " evento" + (filtered.length !== 1 ? "s" : "")} actions={
        <div style={{ display:"flex", gap:8, alignItems:"center", flexWrap:"wrap" }}>
          <div className="tabs" style={{ marginBottom:0 }}>
            {[["todos","Todos"],["hoje","Hoje"],["semana","Semana"],["mes","Mês"]].map(function(p){
              return <button key={p[0]} className={periodoFilter===p[0]?"is-on":""} onClick={function(){ setPeriodoFilter(p[0]); }}>{p[1]}</button>;
            })}
            <button className={periodoFilter==="planejadas"?"is-on":""} onClick={function(){ setPeriodoFilter("planejadas"); }}
              style={{ position:'relative' }}>
              Planejadas
              {planejPendentes > 0 && (
                <span style={{
                  position:'absolute', top:-4, right:-4,
                  background:'var(--warn)', color:'#fff',
                  borderRadius:99, fontSize:9, fontWeight:700,
                  padding:'1px 4px', lineHeight:1.4,
                }}>{planejPendentes}</span>
              )}
            </button>
          </div>
          <div className="tabs" style={{ marginBottom:0 }}>
            {tipos.map(function(t){
              return (
                <button key={t} className={tipoFilter===t?"is-on":""} onClick={function(){ setTipoFilter(t); }}>
                  {t==="todos" ? "Todos" : TIPO_LABEL[t]}
                </button>
              );
            })}
          </div>
        </div>
      }>
        {filtered.length === 0 ? (
          <div style={{ padding:"40px 0", textAlign:"center", color:"var(--tx-3)" }}>
            <i data-lucide="calendar-x" style={{ width:28, height:28, display:"block", margin:"0 auto 10px" }}></i>
            Nenhum compromisso encontrado.
          </div>
        ) : (
          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
            {groups.map(function(entry) {
              var day = entry[0]; var evts = entry[1];
              var d   = new Date(day + "T00:00:00");
              var head = d.toLocaleDateString("pt-BR",{ weekday:"long", day:"2-digit", month:"long" });
              return (
                <div key={day}>
                  <div style={{ font:"600 11px/1 var(--ff-body)", textTransform:"uppercase", letterSpacing:".08em",
                    color:"var(--tx-3)", padding:"6px 0", borderBottom:"1px solid var(--border)", marginBottom:10 }}>
                    {head}
                  </div>
                  <div style={{ display:"flex", flexDirection:"column", gap:8 }}>
                    {evts.map(function(e){
                      return <BigEvent key={e.id} evt={e}
                        onEdit={function(){ abrirEditar(e); }}
                        onNav={onNav}
                        onRealizar={function(){ _abrirAtividadeModal(e); }}
                        onCancelar={function(){ abrirJustif(e); }}
                      />;
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </Panel>

      {/* ── Modal edição ─────────────────────────────── */}
      <Modal open={showEditModal} onClose={fecharEditar} title="Editar compromisso" wide>
        <div className="form-grid-2" style={{ marginTop:16 }}>

          {/* Tipo grid */}
          <FormField label="Tipo" col={2}>
            <div style={{ display:"grid", gridTemplateColumns:"repeat(3,1fr)",
              border:"1px solid var(--border-2)", borderRadius:"var(--r-md)", overflow:"hidden" }}>
              {TIPO_TIPOS.map(function(t, i){
                return (
                  <div key={t} className={"tb-tog " + (eTipo===t ? "on" : "")}
                    style={{
                      display:"flex", alignItems:"center", justifyContent:"center", gap:5,
                      borderRight: (i%3!==2) ? "1px solid var(--border-2)" : "none",
                      borderBottom: i<3 ? "1px solid var(--border-2)" : "none",
                    }}
                    onClick={function(){ setETipo(t); }}>
                    <i data-lucide={TIPO_ICON[t]} style={{ width:13, height:13 }}></i>
                    {TIPO_LABEL[t]}
                  </div>
                );
              })}
            </div>
          </FormField>

          {/* Título */}
          <FormField label="Título" col={2}>
            <input value={eTitulo} onChange={function(e){ setETitulo(e.target.value); }} className="inp"
              placeholder="Ex: Visita técnica ao canteiro de obras..." />
          </FormField>

          {/* Data + Duração */}
          <FormField label="Data e hora">
            <input type="datetime-local" value={eData} onChange={function(e){ setEData(e.target.value); }} className="inp" />
          </FormField>

          <FormField label="Duração" hint="ex: 1h30">
            <input value={eDur} onChange={function(e){ setEDur(e.target.value); }} className="inp" placeholder="1h" />
          </FormField>

          {/* Local */}
          <FormField label="Local" col={2}>
            <input value={eLocal} onChange={function(e){ setELocal(e.target.value); }} className="inp"
              placeholder="Endereço, cidade ou link de reunião..." />
          </FormField>

          {/* Oportunidade — só aparece se o cliente do evento tem oportunidades */}
          {opsDoEvt.length > 0 && (
            <FormField label="Oportunidade" col={2}>
              <select value={eOpId} onChange={function(e){ setEOpId(e.target.value); }} className="inp">
                <option value="">Nenhuma</option>
                {opsDoEvt.map(function(o){ return <option key={o.id} value={o.id}>{o.titulo||o.id}</option>; })}
              </select>
            </FormField>
          )}

          {/* Vendedor */}
          {usuarios.length > 1 && (
            <FormField label="Vendedor" col={2}>
              <select value={eVendId} onChange={function(e){ setEVendId(e.target.value); }} className="inp">
                <option value="">Selecione...</option>
                {usuarios.map(function(v){ return <option key={v.id} value={v.id}>{v.nome}</option>; })}
              </select>
            </FormField>
          )}
        </div>

        {/* Status Outlook */}
        {editEvt && (function(){
          var synced = _agHasOutlook(editEvt.id);
          return (
            <div style={{ marginTop:14, display:"flex", alignItems:"center", gap:8,
              font:"400 12px/1.3 var(--ff-body)",
              color: synced ? "var(--ok)" : "var(--tx-3)",
              background: synced ? "color-mix(in srgb,var(--ok) 8%,var(--surface))" : "var(--surface-2)",
              borderRadius:"var(--r-sm)", padding:"9px 13px" }}>
              <i data-lucide={synced ? "calendar-check" : "calendar-plus"} style={{ width:13, height:13, flexShrink:0 }}></i>
              {synced
                ? "Sincronizado com o Outlook · lembrete 30 min antes"
                : "Ao salvar, um evento será criado no Outlook com lembrete de 30 min."}
            </div>
          );
        })()}

        {/* Rodapé */}
        <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center",
          gap:10, marginTop:24, paddingTop:16, borderTop:"1px solid var(--border)" }}>
          {editEvt && editEvt.origem === 'planejador' ? (
            <span style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-3)', display:'flex', alignItems:'center', gap:5 }}>
              <i data-lucide="info" style={{ width:12, height:12 }}></i>
              Para cancelar, use a opção na lista da agenda.
            </span>
          ) : (
            <button className="btn btn-ghost" style={{ color:"var(--danger)" }}
              onClick={function(){ editEvt && excluirEvento(editEvt); }}>
              <i data-lucide="trash-2" style={{ width:13, height:13 }}></i>
              Excluir
            </button>
          )}
          <div style={{ display:"flex", gap:10 }}>
            {editEvt && (eOpId || editEvt.op_id) && (
              <button className="btn btn-secondary"
                onClick={function(){ onNav && onNav("oportunidade", eOpId || editEvt.op_id); fecharEditar(); }}>
                <i data-lucide="external-link" style={{ width:13, height:13 }}></i>
                Ver oportunidade
              </button>
            )}
            <button className="btn btn-secondary" onClick={fecharEditar} disabled={saving || syncing}>Cancelar</button>
            <button className="btn btn-primary" onClick={salvarEdicao} disabled={saving || syncing}>
              {syncing ? "Sincronizando Outlook..." : saving ? "Salvando..." : "Salvar compromisso"}
            </button>
          </div>
        </div>
      </Modal>

      <PlanejadorSemana
        open={showPlanejador}
        onClose={function(){ setShowPlanejador(false); }}
        onFinalizado={function(){ setTick(function(t){ return t+1; }); }}
      />

      <JustificativaModal
        open={showJustif}
        onClose={fecharJustif}
        evt={justifEvt}
        onSalvo={_onJustifSalva}
      />

    </div>
  );
}
// ── JustificativaModal ───────────────────────────────────────────────────────
function JustificativaModal({ open, onClose, evt, onSalvo }) {
  var [cat,    setCat]    = useAgState('');
  var [desc,   setDesc]   = useAgState('');
  var [saving, setSaving] = useAgState(false);

  function _fechar() { setCat(''); setDesc(''); setSaving(false); onClose(); }

  async function _salvar() {
    if (!cat) { window.CRM_TOAST('Selecione uma justificativa.', 'warn'); return; }
    if (cat === 'outros' && !desc.trim()) { window.CRM_TOAST('Descreva o motivo em "Outros".', 'warn'); return; }
    setSaving(true);
    try {
      var campos = {
        status_visita:           'cancelada',
        justificativa_categoria: cat,
        justificativa_descricao: desc.trim() || '',
      };
      Object.assign(evt, campos);
      if (typeof CRM_API !== 'undefined' && evt._spId) {
        await CRM_API.updateItem('Agenda', evt._spId, campos);
      }
      _fechar();
      if (typeof onSalvo === 'function') onSalvo();
    } catch(e) {
      window.CRM_TOAST('Erro: ' + e.message, 'error');
      setSaving(false);
    }
  }

  if (!open || !evt) return null;
  return (
    <Modal open={open} onClose={_fechar} title="Cancelar visita planejada">
      <div style={{ marginTop:16 }}>
        <div style={{ display:'flex', flexDirection:'column', gap:6, marginBottom:16 }}>
          {JUSTIF_CANCELAR.map(function(j) {
            var sel = cat === j.cat;
            return (
              <label key={j.cat} style={{
                display:'flex', alignItems:'center', gap:10, cursor:'pointer',
                padding:'9px 12px', borderRadius:'var(--r-sm)',
                background: sel ? 'color-mix(in srgb,var(--danger) 8%,var(--surface))' : 'var(--surface-2)',
                border:'1px solid ' + (sel ? 'var(--danger)' : 'var(--border)'),
                transition:'all 120ms',
              }}>
                <input type="radio" name="justif" value={j.cat}
                  checked={sel}
                  onChange={function(){ setCat(j.cat); setDesc(''); }}
                  style={{ accentColor:'var(--danger)', flexShrink:0 }} />
                <span style={{ font:'500 13px/1.3 var(--ff-body)', color:'var(--tx)' }}>{j.label}</span>
              </label>
            );
          })}
        </div>
        {cat === 'outros' && (
          <FormField label="Descreva o motivo">
            <textarea value={desc} onChange={function(e){ setDesc(e.target.value); }}
              className="inp" rows={3}
              placeholder="Descreva brevemente o que ocorreu..." />
          </FormField>
        )}
        <div style={{ display:'flex', justifyContent:'flex-end', gap:10, marginTop:20 }}>
          <button className="btn btn-secondary" onClick={_fechar} disabled={saving}>Voltar</button>
          <button className="btn" style={{ background:'var(--danger)', color:'#fff', border:'none' }}
            onClick={_salvar} disabled={saving || !cat}>
            {saving ? 'Salvando...' : '🚫 Confirmar cancelamento'}
          </button>
        </div>
      </div>
    </Modal>
  );
}

// ── PlanejadorSemana ────────────────────────────────────────────────────────

var CLASSE_BADGE_STYLE = {
  'Grande conta': { bg:'#fff3cd', color:'#7a5800', border:'#f4a300' },
  'A':            { bg:'#d4edda', color:'#155724', border:'#28a745' },
  'B':            { bg:'#cce5ff', color:'#004085', border:'#3370b7' },
  'C':            { bg:'#e2e3e5', color:'#383d41', border:'#999'    },
  'D':            { bg:'#f8d7da', color:'#721c24', border:'#e07070' },
};

var PLANNER_SLOTS = [
  { label:'09h–11h', hora:9  },
  { label:'14h–16h', hora:14 },
];

var DIAS_SEMANA = ['Seg','Ter','Qua','Qui','Sex'];

function _planejadorScore(cli, hoje, semIni, semFim) {
  var score = 0, motivo = '';
  if (cli.proxima_visita) {
    var prox = new Date(cli.proxima_visita);
    if (prox < hoje) {
      var d = Math.round((hoje - prox) / 864e5);
      score += 100;
      motivo = 'Vencida há ' + d + ' dia' + (d > 1 ? 's' : '');
    } else if (prox >= semIni && prox <= semFim) {
      score += 50;
      motivo = 'Prevista esta semana';
    }
  }
  var cs = {'Grande conta':40,'A':30,'B':20,'C':10,'D':5};
  score += cs[cli.classe] || 0;
  if (cli.ultima_visita) {
    var dias = Math.round((hoje - new Date(cli.ultima_visita)) / 864e5);
    score += Math.min(dias, 30);
    if (!motivo) motivo = 'Última há ' + dias + 'd';
  } else {
    score += 30;
    if (!motivo) motivo = 'Sem visita registrada';
  }
  return { score: score, motivo: motivo };
}

function _semanaIni(offset) {
  var d = new Date();
  d.setHours(0, 0, 0, 0);
  d.setDate(d.getDate() - ((d.getDay() + 6) % 7) + offset * 7);
  return d;
}

function _semLabel(ini) {
  var fim = new Date(ini); fim.setDate(fim.getDate() + 4);
  var fmt = function(dd) { return dd.toLocaleDateString('pt-BR', { day:'2-digit', month:'2-digit' }); };
  return fmt(ini) + ' – ' + fmt(fim);
}

function ClasseBadge({ classe }) {
  var s = CLASSE_BADGE_STYLE[classe];
  if (!s) return null;
  return (
    <span style={{
      display:'inline-block', fontSize:10, fontWeight:700, lineHeight:1,
      padding:'2px 6px', borderRadius:99, border:'1px solid ' + s.border,
      background:s.bg, color:s.color, whiteSpace:'nowrap',
    }}>{classe}</span>
  );
}

function PlanejadorSemana({ open, onClose, onFinalizado }) {
  // ── fases: config | preview | salvando
  var [fase,       setFase]       = useAgState('config');
  var [semOffset,  setSemOffset]  = useAgState(1);
  var [diasSel,    setDiasSel]    = useAgState([0,1,2,3,4]); // índices 0-4 = Seg-Sex
  var [munisBusca, setMunisBusca] = useAgState('');
  var [munisSel,   setMunisSel]   = useAgState([]);
  var [ufSel,      setUfSel]      = useAgState('');   // '' = todas; senão filtra municípios por UF
  var [segSel,     setSegSel]     = useAgState('');

  // preview
  var [grid,       setGrid]       = useAgState(null);   // {diaIdx: [cli|null, cli|null, cli|null, cli|null]}
  var [reserva,    setReserva]    = useAgState([]);
  var [subst,      setSubst]      = useAgState(null);   // {diaIdx, slotIdx} | null

  // salvando
  var [progTotal,  setProgTotal]  = useAgState(0);
  var [progDone,   setProgDone]   = useAgState(0);

  // derivados — hooks ANTES do early return (Rules of Hooks)
  var hoje   = new Date(); hoje.setHours(0,0,0,0);
  var semIni = _semanaIni(semOffset);
  var semFim = new Date(semIni); semFim.setDate(semFim.getDate() + 4); semFim.setHours(23,59,59,999);

  // Identidade efetiva (centralizada em CRM_USER, reativa a "Visualizar como")
  var _emailLogado = (window.CRM_USER && window.CRM_USER.email) || '';
  var userLogado = (CRM_DATA.usuarios || []).find(function(u) {
    return u.email && _emailLogado && u.email.toLowerCase() === _emailLogado;
  }) || (CRM_DATA.usuarios || [])[0] || { id:'', email:'' };
  var userEmail  = userLogado.email || userLogado.id || '';
  var isGerente  = !!(window.CRM_USER && window.CRM_USER.isGerente);

  // Re-inicializa ícones Lucide quando a fase muda (modal montado dinamicamente)
  useAgEffect(function() {
    if (typeof lucide !== 'undefined') lucide.createIcons();
  }, [fase, open]);

  var clientes = CRM_DATA.clientes || [];
  var agendaArr = CRM_DATA.agenda   || [];

  // municípios disponíveis agrupados por UF + contagem (gerente vê todos)
  var munisDisp = useAgMemo(function() {
    var map = {}; // { UF: { cidade: count } }
    clientes.forEach(function(c) {
      if (c.status === 'inativo') return;
      if (!isGerente && c.vendedor_id !== userEmail && c.vendedor_id !== userLogado.id) return;
      if (!c.cidade) return;
      var uf = (c.uf || 'N/A').toUpperCase();
      if (!map[uf]) map[uf] = {};
      map[uf][c.cidade] = (map[uf][c.cidade] || 0) + 1;
    });
    return Object.keys(map).sort().map(function(uf) {
      return {
        uf: uf,
        cidades: Object.keys(map[uf]).sort().map(function(cidade) {
          return { cidade: cidade, count: map[uf][cidade] };
        }),
      };
    });
  }, [clientes, userEmail, isGerente]);

  var munisFiltrados = useAgMemo(function() {
    var base = ufSel ? munisDisp.filter(function(g) { return g.uf === ufSel; }) : munisDisp;
    if (!munisBusca.trim()) return base;
    var q = munisBusca.toLowerCase();
    return base.map(function(g) {
      return { uf: g.uf, cidades: g.cidades.filter(function(c) { return c.cidade.toLowerCase().indexOf(q) !== -1; }) };
    }).filter(function(g) { return g.cidades.length > 0; });
  }, [munisDisp, munisBusca, ufSel]);

  // segmentos disponíveis
  var segsDisp = useAgMemo(function() {
    var set = new Set();
    clientes.forEach(function(c) {
      if (c.segmento) set.add(c.segmento);
    });
    return Array.from(set).sort();
  }, [clientes]);

  if (!open) return null;

  // eventos existentes por dia da semana
  function _evtsDoDia(diaIdx) {
    var dia = new Date(semIni); dia.setDate(dia.getDate() + diaIdx);
    var key = dia.toISOString().slice(0,10);
    return agendaArr.filter(function(e) { return (e.data||'').slice(0,10) === key; });
  }

  // ── Reset ao fechar ──────────────────────────────────────────────────────
  function _fechar() {
    setFase('config');
    setSemOffset(1);
    setDiasSel([0,1,2,3,4]);
    setMunisBusca('');
    setMunisSel([]);
    setUfSel('');
    setSegSel('');
    setGrid(null);
    setReserva([]);
    setSubst(null);
    setProgTotal(0);
    setProgDone(0);
    onClose();
  }

  // ── Toggle dia ───────────────────────────────────────────────────────────
  function _toggleDia(idx) {
    setDiasSel(function(prev) {
      return prev.indexOf(idx) === -1
        ? prev.concat([idx]).sort()
        : prev.filter(function(x) { return x !== idx; });
    });
  }

  // ── Toggle município ─────────────────────────────────────────────────────
  function _toggleMuni(m) {
    setMunisSel(function(prev) {
      return prev.indexOf(m) === -1
        ? prev.concat([m])
        : prev.filter(function(x) { return x !== m; });
    });
  }

  // ── Gerar sugestão ───────────────────────────────────────────────────────
  function _gerarSugestao() {
    if (diasSel.length === 0) { window.CRM_TOAST('Selecione ao menos um dia.', 'warn'); return; }
    if (munisSel.length === 0) { window.CRM_TOAST('Selecione ao menos um município.', 'warn'); return; }

    // candidatos
    var candidatos = clientes.filter(function(c) {
      if (c.status === 'inativo') return false;
      if (!isGerente && c.vendedor_id !== userEmail && c.vendedor_id !== userLogado.id) return false;
      if (!c.cidade || munisSel.indexOf(c.cidade) === -1) return false;
      if (segSel && c.segmento !== segSel) return false;
      return true;
    }).map(function(c) {
      var r = _planejadorScore(c, hoje, semIni, semFim);
      return { cli:c, score:r.score, motivo:r.motivo };
    }).sort(function(a, b) { return b.score - a.score; });

    var totalSlots = diasSel.length * PLANNER_SLOTS.length;
    var alocados   = candidatos.slice(0, totalSlots);
    var reservaArr = candidatos.slice(totalSlots).map(function(x) { return x; });

    // montar grid: diaIdx -> [slot0, slot1, slot2, slot3]
    var gridObj = {};
    var cursor  = 0;
    diasSel.forEach(function(diaIdx) {
      gridObj[diaIdx] = PLANNER_SLOTS.map(function() {
        return cursor < alocados.length ? alocados[cursor++] : null;
      });
    });

    setGrid(gridObj);
    setReserva(reservaArr);
    setSubst(null);
    setFase('preview');
  }

  // ── Remover célula (vai para reserva) ───────────────────────────────────
  function _removerCelula(diaIdx, slotIdx) {
    setGrid(function(prev) {
      var copia = Object.assign({}, prev);
      var arr   = copia[diaIdx].slice();
      var removido = arr[slotIdx];
      arr[slotIdx] = null;
      copia[diaIdx] = arr;
      if (removido) setReserva(function(r) { return r.concat([removido]); });
      return copia;
    });
    setSubst(null);
  }

  // ── Substituir célula por item da reserva ────────────────────────────────
  function _substituir(diaIdx, slotIdx, itemReserva) {
    setGrid(function(prev) {
      var copia   = Object.assign({}, prev);
      var arr     = copia[diaIdx].slice();
      var antigo  = arr[slotIdx];
      arr[slotIdx] = itemReserva;
      copia[diaIdx] = arr;
      if (antigo) setReserva(function(r) { return r.concat([antigo]); });
      return copia;
    });
    setReserva(function(r) { return r.filter(function(x) { return x !== itemReserva; }); });
    setSubst(null);
  }

  // ── Contar visitas no grid ───────────────────────────────────────────────
  function _contarVisitas() {
    if (!grid) return { total:0, dias:0 };
    var total = 0, dias = 0;
    diasSel.forEach(function(diaIdx) {
      var slots = grid[diaIdx] || [];
      var nDia  = slots.filter(Boolean).length;
      if (nDia > 0) { total += nDia; dias++; }
    });
    return { total:total, dias:dias };
  }

  // ── Finalizar agenda (save loop) ─────────────────────────────────────────
  async function _finalizar() {
    if (!grid) return;
    var itens = [];
    diasSel.forEach(function(diaIdx) {
      var dia = new Date(semIni); dia.setDate(dia.getDate() + diaIdx);
      (grid[diaIdx] || []).forEach(function(item, slotIdx) {
        if (!item) return;
        var slot = PLANNER_SLOTS[slotIdx];
        var dataEvt = new Date(dia);
        dataEvt.setHours(slot.hora, 0, 0, 0);
        itens.push({ item:item, dataEvt:dataEvt });
      });
    });

    if (itens.length === 0) { window.CRM_TOAST('Nenhuma visita para agendar.', 'warn'); return; }

    setProgTotal(itens.length);
    setProgDone(0);
    setFase('salvando');

    var vendId = userLogado.id || userEmail;

    for (var i = 0; i < itens.length; i++) {
      var entry = itens[i];
      var cli   = entry.item.cli;
      var ag    = {
        id:         'AG-' + Date.now() + '-' + i,
        tipo:       'visita',
        titulo:     'Visita · ' + (cli.razao || cli.id),
        cliente_id: cli.id,
        op_id:      '',
        vendedor_id: vendId,
        data:       entry.dataEvt.toISOString(),
        duracao:    '2h',
        local:      cli.cidade || '',
        origem:     'planejador',
      };
      try {
        await CRM_API.addItem('Agenda', ag);
      } catch(e) {
        console.warn('[Planejador] addItem:', e.message);
      }
      CRM_DATA.agenda.push(ag);
      try {
        await CRM_API.criarEventoOutlook(ag);
      } catch(e) {
        console.warn('[Planejador] outlook:', e.message);
      }
      setProgDone(i + 1);
    }

    if (typeof window.showCrmToast === 'function') {
      window.showCrmToast(itens.length + ' visita(s) agendada(s) com sucesso', 'ok');
    }
    onFinalizado && onFinalizado();
    _fechar();
  }

  // ────────────────────────────────────────────────────────────────────────
  // RENDER
  // ────────────────────────────────────────────────────────────────────────

  // ── FASE SALVANDO ────────────────────────────────────────────────────────
  if (fase === 'salvando') {
    var pct = progTotal > 0 ? Math.round((progDone / progTotal) * 100) : 0;
    return (
      <Modal open={true} onClose={function(){}} title="Agendando visitas..." wide>
        <div style={{ padding:'32px 0', textAlign:'center' }}>
          <i data-lucide="calendar-plus" style={{ width:40, height:40, color:'var(--grn)', display:'block', margin:'0 auto 16px' }}></i>
          <div style={{ font:'600 15px/1.4 var(--ff-body)', color:'var(--tx)', marginBottom:20 }}>
            Criando evento {progDone} de {progTotal}...
          </div>
          <div style={{ background:'var(--surface-2)', borderRadius:99, height:8, overflow:'hidden', maxWidth:320, margin:'0 auto' }}>
            <div style={{
              height:'100%', borderRadius:99,
              background:'var(--grn)',
              width: pct + '%',
              transition:'width 300ms ease',
            }}></div>
          </div>
          <div style={{ font:'400 11px/1 var(--ff-mono)', color:'var(--tx-3)', marginTop:10 }}>{pct}%</div>
        </div>
      </Modal>
    );
  }

  // ── FASE PREVIEW ─────────────────────────────────────────────────────────
  if (fase === 'preview') {
    var cv = _contarVisitas();
    return (
      <Modal open={true} onClose={_fechar} title="Prévia da semana planejada" xl>
        <div style={{ overflowX:'auto', marginTop:16 }}>
          <table style={{ borderCollapse:'collapse', minWidth: diasSel.length * 180, width:'100%' }}>
            <thead>
              <tr>
                <th style={{ width:80, padding:'6px 8px', font:'600 11px/1 var(--ff-body)', color:'var(--tx-3)',
                  textAlign:'left', borderBottom:'2px solid var(--border)' }}></th>
                {diasSel.map(function(diaIdx) {
                  var dia = new Date(semIni); dia.setDate(dia.getDate() + diaIdx);
                  return (
                    <th key={diaIdx} style={{ padding:'6px 8px', font:'600 12px/1.4 var(--ff-body)',
                      color:'var(--tx)', textAlign:'center', borderBottom:'2px solid var(--border)',
                      minWidth:160 }}>
                      <div>{DIAS_SEMANA[diaIdx]}</div>
                      <div style={{ font:'400 11px/1 var(--ff-mono)', color:'var(--tx-3)' }}>
                        {dia.toLocaleDateString('pt-BR', { day:'2-digit', month:'2-digit' })}
                      </div>
                    </th>
                  );
                })}
              </tr>
            </thead>
            <tbody>
              {PLANNER_SLOTS.map(function(slot, slotIdx) {
                return (
                  <tr key={slotIdx}>
                    <td style={{ padding:'6px 8px', font:'500 11px/1 var(--ff-mono)', color:'var(--tx-3)',
                      verticalAlign:'top', whiteSpace:'nowrap', borderBottom:'1px solid var(--border)' }}>
                      {slot.label}
                    </td>
                    {diasSel.map(function(diaIdx) {
                      var item      = (grid[diaIdx] || [])[slotIdx];
                      var isSubst   = subst && subst.diaIdx === diaIdx && subst.slotIdx === slotIdx;
                      return (
                        <td key={diaIdx} style={{ padding:4, verticalAlign:'top',
                          borderBottom:'1px solid var(--border)', borderLeft:'1px solid var(--border)' }}>
                          {item ? (
                            <div>
                              <div style={{
                                background:'var(--surface)', border:'1px solid var(--border)',
                                borderRadius:'var(--r-sm)', padding:'8px 10px', position:'relative',
                              }}>
                                <div style={{ paddingRight:36 }}>
                                  <div style={{ font:'600 12px/1.3 var(--ff-body)', color:'var(--tx)',
                                    overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap',
                                    maxWidth:130 }}>
                                    {item.cli.razao || item.cli.id}
                                  </div>
                                  <div style={{ marginTop:4 }}>
                                    <ClasseBadge classe={item.cli.classe} />
                                  </div>
                                  {item.motivo && (
                                    <div style={{ font:'400 10px/1.3 var(--ff-mono)', color:'var(--tx-3)', marginTop:4 }}>
                                      {item.motivo}
                                    </div>
                                  )}
                                </div>
                                <div style={{ position:'absolute', top:6, right:6, display:'flex', flexDirection:'column', gap:3 }}>
                                  <button title="Remover" onClick={function(){ _removerCelula(diaIdx, slotIdx); }}
                                    style={{ border:'none', background:'transparent', cursor:'pointer',
                                      color:'var(--danger)', padding:2, lineHeight:1, fontSize:13 }}>✕</button>
                                  <button title="Substituir" onClick={function(){
                                      if (!isSubst && reserva.length === 0) {
                                        if (typeof window.showCrmToast === 'function')
                                          window.showCrmToast('Sem clientes na reserva para essa região.', 'warn');
                                        return;
                                      }
                                      setSubst(isSubst ? null : { diaIdx:diaIdx, slotIdx:slotIdx });
                                    }}
                                    style={{ border:'none', background:'transparent', cursor:'pointer',
                                      color:'var(--info)', padding:2, lineHeight:1, fontSize:13 }}>🔄</button>
                                </div>
                              </div>
                              {isSubst && (
                                <div style={{
                                  marginTop:4, background:'var(--surface-2)', border:'1px solid var(--border)',
                                  borderRadius:'var(--r-sm)', padding:6, maxHeight:140, overflowY:'auto',
                                }}>
                                  {reserva.length === 0 ? (
                                    <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-3)', textAlign:'center', padding:'8px 4px' }}>
                                      <span style={{ fontSize:14 }}>↗</span> Sem clientes disponíveis. Considere prospectar nessa região.
                                    </div>
                                  ) : reserva.map(function(r, ri) {
                                    return (
                                      <div key={ri} onClick={function(){ _substituir(diaIdx, slotIdx, r); }}
                                        style={{
                                          padding:'5px 7px', borderRadius:'var(--r-sm)', cursor:'pointer',
                                          font:'500 11px/1.3 var(--ff-body)', color:'var(--tx)',
                                          borderBottom: ri < reserva.length-1 ? '1px solid var(--border)' : 'none',
                                        }}
                                        onMouseEnter={function(e){ e.currentTarget.style.background='var(--surface)'; }}
                                        onMouseLeave={function(e){ e.currentTarget.style.background='transparent'; }}
                                      >
                                        <div style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                                          {r.cli.razao || r.cli.id}
                                        </div>
                                        <div style={{ display:'flex', gap:4, alignItems:'center', marginTop:2 }}>
                                          <ClasseBadge classe={r.cli.classe} />
                                          {r.motivo && <span style={{ font:'400 10px/1 var(--ff-mono)', color:'var(--tx-3)' }}>{r.motivo}</span>}
                                        </div>
                                      </div>
                                    );
                                  })}
                                </div>
                              )}
                            </div>
                          ) : (
                            <div>
                              <div style={{
                                background:'var(--surface-2)', border:'1px dashed var(--border)',
                                borderRadius:'var(--r-sm)', height:72, display:'flex',
                                alignItems:'center', justifyContent:'center',
                                color:'var(--tx-3)', fontSize:18,
                                cursor: reserva.length > 0 ? 'pointer' : 'default',
                                transition:'background 120ms',
                              }}
                                title={reserva.length > 0 ? 'Adicionar cliente neste horário' : 'Sem clientes disponíveis'}
                                onClick={function(){
                                  if (reserva.length === 0) {
                                    if (typeof window.showCrmToast === 'function')
                                      window.showCrmToast('Sem clientes na reserva para essa região.', 'warn');
                                    return;
                                  }
                                  setSubst(isSubst ? null : { diaIdx:diaIdx, slotIdx:slotIdx });
                                }}
                                onMouseEnter={function(e){ if (reserva.length > 0) e.currentTarget.style.background='var(--border)'; }}
                                onMouseLeave={function(e){ e.currentTarget.style.background='var(--surface-2)'; }}
                              >+</div>
                              {isSubst && reserva.length > 0 && (
                                <div style={{
                                  marginTop:4, background:'var(--surface-2)', border:'1px solid var(--border)',
                                  borderRadius:'var(--r-sm)', padding:6, maxHeight:140, overflowY:'auto',
                                }}>
                                  {reserva.map(function(r, ri) {
                                    return (
                                      <div key={ri} onClick={function(){ _substituir(diaIdx, slotIdx, r); }}
                                        style={{
                                          padding:'5px 7px', borderRadius:'var(--r-sm)', cursor:'pointer',
                                          font:'500 11px/1.3 var(--ff-body)', color:'var(--tx)',
                                          borderBottom: ri < reserva.length-1 ? '1px solid var(--border)' : 'none',
                                        }}
                                        onMouseEnter={function(e){ e.currentTarget.style.background='var(--surface)'; }}
                                        onMouseLeave={function(e){ e.currentTarget.style.background='transparent'; }}
                                      >
                                        <div style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                                          {r.cli.razao || r.cli.id}
                                        </div>
                                        <div style={{ display:'flex', gap:4, alignItems:'center', marginTop:2 }}>
                                          <ClasseBadge classe={r.cli.classe} />
                                          {r.motivo && <span style={{ font:'400 10px/1 var(--ff-mono)', color:'var(--tx-3)' }}>{r.motivo}</span>}
                                        </div>
                                      </div>
                                    );
                                  })}
                                </div>
                              )}
                            </div>
                          )}
                        </td>
                      );
                    })}
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>

        {/* Rodapé preview */}
        <div style={{ marginTop:18, padding:'14px 0 0', borderTop:'1px solid var(--border)' }}>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:12, flexWrap:'wrap' }}>
            <div style={{ font:'400 12px/1.5 var(--ff-body)', color:'var(--tx-2)' }}>
              <span style={{ fontWeight:600 }}>{cv.total} visita(s)</span> em {cv.dias} dia(s)
              <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--warn)', marginTop:4 }}>
                ⚠ Ao finalizar, {cv.total} evento(s) serão criados na sua agenda e no Outlook.
              </div>
            </div>
            <div style={{ display:'flex', gap:10 }}>
              <button className="btn btn-secondary" onClick={function(){ setFase('config'); setSubst(null); }}>
                <i data-lucide="arrow-left" style={{ width:13, height:13 }}></i> Voltar
              </button>
              <button className="btn btn-primary" onClick={_finalizar} disabled={cv.total === 0}>
                Finalizar agenda <i data-lucide="arrow-right" style={{ width:13, height:13 }}></i>
              </button>
            </div>
          </div>
        </div>
      </Modal>
    );
  }

  // ── FASE CONFIG ──────────────────────────────────────────────────────────
  return (
    <Modal open={true} onClose={_fechar} title="Planejar semana de visitas" xl>
      <div style={{ marginTop:16 }}>

        {/* Navegação de semana */}
        <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:20 }}>
          <button className="btn btn-secondary" style={{ padding:'5px 10px' }}
            onClick={function(){ setSemOffset(function(o){ return o-1; }); }}>
            <i data-lucide="chevron-left" style={{ width:14, height:14 }}></i>
          </button>
          <div style={{ flex:1, textAlign:'center', font:'500 13px/1 var(--ff-body)', color:'var(--tx)' }}>
            Semana de {_semLabel(semIni)}
          </div>
          <button className="btn btn-secondary" style={{ padding:'5px 10px' }}
            onClick={function(){ setSemOffset(function(o){ return o+1; }); }}>
            <i data-lucide="chevron-right" style={{ width:14, height:14 }}></i>
          </button>
        </div>

        {/* Dias da semana */}
        <div style={{ marginBottom:20 }}>
          <div style={{ font:'600 11px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.08em',
            color:'var(--tx-3)', marginBottom:8 }}>Dias da semana</div>
          <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
            {DIAS_SEMANA.map(function(nome, idx) {
              var sel    = diasSel.indexOf(idx) !== -1;
              var evtsN  = _evtsDoDia(idx).length;
              return (
                <label key={idx} style={{
                  display:'flex', flexDirection:'column', alignItems:'center', gap:3,
                  padding:'8px 14px', borderRadius:'var(--r-md)', cursor:'pointer',
                  border:'1.5px solid ' + (sel ? 'var(--grn)' : 'var(--border)'),
                  background: sel ? 'color-mix(in srgb,var(--grn) 8%,var(--surface))' : 'var(--surface)',
                  transition:'all 150ms',
                }}>
                  <input type="checkbox" checked={sel} onChange={function(){ _toggleDia(idx); }}
                    style={{ display:'none' }} />
                  <span style={{ font:'600 13px/1 var(--ff-body)', color: sel ? 'var(--grn)' : 'var(--tx)' }}>{nome}</span>
                  {evtsN > 0 && (
                    <span style={{ font:'400 10px/1 var(--ff-mono)', color:'var(--warn)', marginTop:2 }}>
                      {evtsN} evento(s) já agendado(s)
                    </span>
                  )}
                </label>
              );
            })}
          </div>
        </div>

        {/* Municípios */}
        <div style={{ marginBottom:20 }}>
          <div style={{ font:'600 11px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.08em',
            color:'var(--tx-3)', marginBottom:8 }}>Municípios</div>
          {/* UF + busca lado a lado */}
          <div style={{ display:'flex', gap:8, marginBottom:6 }}>
            <select className="inp" value={ufSel}
              onChange={function(e){ setUfSel(e.target.value); }}
              style={{ width:120, flexShrink:0 }}>
              <option value="">Todas UFs</option>
              {munisDisp.map(function(g) {
                var totalCli = g.cidades.reduce(function(s, c){ return s + c.count; }, 0);
                return <option key={g.uf} value={g.uf}>{g.uf} ({totalCli})</option>;
              })}
            </select>
            <input className="inp" placeholder={ufSel ? 'Buscar em ' + ufSel + '...' : 'Buscar município...'}
              value={munisBusca}
              onChange={function(e){ setMunisBusca(e.target.value); }}
              style={{ flex:1 }} />
          </div>
          <div style={{
            maxHeight:220, overflowY:'auto', border:'1px solid var(--border)',
            borderRadius:'var(--r-md)', padding:'4px 0',
            background:'var(--surface)',
          }}>
            {munisFiltrados.length === 0 ? (
              <div style={{ padding:'12px 14px', font:'400 12px/1 var(--ff-body)', color:'var(--tx-3)' }}>
                Nenhum município encontrado.
              </div>
            ) : munisFiltrados.map(function(grupo) {
              return (
                <div key={grupo.uf}>
                  {/* Cabeçalho UF */}
                  <div style={{
                    padding:'5px 14px 3px', font:'700 10px/1 var(--ff-body)',
                    textTransform:'uppercase', letterSpacing:'.1em',
                    color:'var(--tx-3)', background:'var(--surface-2)',
                    borderTop:'1px solid var(--border)', borderBottom:'1px solid var(--border)',
                    position:'sticky', top:0,
                  }}>{grupo.uf}</div>
                  {grupo.cidades.map(function(item) {
                    var sel = munisSel.indexOf(item.cidade) !== -1;
                    return (
                      <label key={item.cidade} style={{
                        display:'flex', alignItems:'center', gap:8, padding:'6px 14px',
                        cursor:'pointer',
                        background: sel ? 'color-mix(in srgb,var(--grn) 8%,var(--surface))' : 'transparent',
                        transition:'background 100ms',
                      }}>
                        <input type="checkbox" checked={sel} onChange={function(){ _toggleMuni(item.cidade); }}
                          style={{ accentColor:'var(--grn)', flexShrink:0 }} />
                        <span style={{ font:'400 12px/1.3 var(--ff-body)', color:'var(--tx)', flex:1 }}>{item.cidade}</span>
                        <span style={{ font:'400 10px/1 var(--ff-mono)', color:'var(--tx-3)', flexShrink:0 }}>
                          {item.count} cliente{item.count !== 1 ? 's' : ''}
                        </span>
                      </label>
                    );
                  })}
                </div>
              );
            })}
          </div>
          {munisSel.length > 0 && (
            <div style={{ font:'400 11px/1 var(--ff-mono)', color:'var(--grn)', marginTop:5 }}>
              ✓ {munisSel.length} município(s) selecionado(s)
            </div>
          )}
        </div>

        {/* Segmento */}
        <div style={{ marginBottom:24 }}>
          <div style={{ font:'600 11px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.08em',
            color:'var(--tx-3)', marginBottom:8 }}>Segmento</div>
          <select className="inp" value={segSel} onChange={function(e){ setSegSel(e.target.value); }}
            style={{ maxWidth:280 }}>
            <option value="">Todos os segmentos</option>
            {segsDisp.map(function(s) { return <option key={s} value={s}>{s}</option>; })}
          </select>
        </div>

        {/* Rodapé config */}
        <div style={{ display:'flex', justifyContent:'flex-end', gap:10,
          paddingTop:16, borderTop:'1px solid var(--border)' }}>
          <button className="btn btn-secondary" onClick={_fechar}>Cancelar</button>
          <button className="btn btn-primary" onClick={_gerarSugestao}>
            Gerar sugestão <i data-lucide="arrow-right" style={{ width:13, height:13 }}></i>
          </button>
        </div>

      </div>
    </Modal>
  );
}

window.Agenda = Agenda;

// ── Sub-componentes ──────────────────────────────────────────────────────────

function KpiAg({ eyebrow, valor, icon, cor }) {
  return (
    <div className="kpi-card" style={{ borderTop:"3px solid " + cor }}>
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"flex-start" }}>
        <div className="kpi-card__eyebrow">{eyebrow}</div>
        <i data-lucide={icon} style={{ width:16, height:16, color:cor }}></i>
      </div>
      <div className="kpi-card__v" style={{ fontSize:44 }}>{valor}</div>
    </div>
  );
}

function MiniEvent({ evt, onEdit }) {
  var cor  = TIPO_COLOR[evt.tipo] || "var(--grn)";
  var time = (evt.data || '').slice(11, 16);
  return (
    <div onClick={onEdit} style={{
      borderLeft:"3px solid " + cor, background:cor + "15",
      padding:"6px 8px", borderRadius:"var(--r-sm)", cursor:"pointer",
    }}>
      <div style={{ font:"500 11px/1.2 var(--ff-body)", color:"var(--tx)",
        display:"-webkit-box", WebkitBoxOrient:"vertical", WebkitLineClamp:2, overflow:"hidden" }}>
        {evt.titulo}
      </div>
      <div style={{ font:"400 10px/1 var(--ff-mono)", color:"var(--tx-3)", marginTop:4 }}>{time}</div>
    </div>
  );
}

function BigEvent({ evt, onEdit, onNav, onRealizar, onCancelar }) {
  var cor  = TIPO_COLOR[evt.tipo] || "var(--grn)";
  var ic   = TIPO_ICON[evt.tipo]  || "calendar";
  var time = (evt.data || '').slice(11, 16);
  var op   = CRM_DATA.getOp(evt.op_id);
  var cli  = op ? CRM_DATA.getCliente(op.cliente_id) : CRM_DATA.getCliente(evt.cliente_id);
  var vend = CRM_DATA.getUsuario(evt.vendedor_id);
  var synced = _agHasOutlook(evt.id);

  // ── Lógica visual para visitas planejadas ──
  var isPlanejada = evt.origem === 'planejador';
  var statusVisita = evt.status_visita || '';
  var hoje = new Date(); hoje.setHours(0,0,0,0);
  var evtDate = evt.data ? new Date(evt.data) : null;
  var isPast = evtDate && evtDate < hoje;
  var isPendente = isPlanejada && isPast && !statusVisita;

  // Cor de borda / fundo extra para estados
  var borderStyle = "1px solid var(--border)";
  var bgExtra = "var(--surface)";
  if (isPlanejada) {
    if (statusVisita === 'realizada')    { borderStyle = "1px solid var(--ok)";     bgExtra = "var(--ok-bg,#f0fff4)"; }
    else if (statusVisita === 'nao_realizada') { borderStyle = "1px solid var(--danger)"; bgExtra = "var(--surface)"; }
    else if (statusVisita === 'cancelada')    { borderStyle = "1px dashed #aaa";          bgExtra = "var(--surface-2)"; }
    else if (isPendente)                      { borderStyle = "2px dashed var(--warn)";   bgExtra = "#fffbf0"; }
    else                                      { borderStyle = "1px dashed var(--border)"; bgExtra = "var(--surface)"; }
  }

  // Badge de status
  var statusBadge = null;
  if (statusVisita === 'realizada')    statusBadge = { label:'✅ Realizada',    color:'var(--ok)' };
  else if (statusVisita === 'nao_realizada') statusBadge = { label:'❌ Não realizada', color:'var(--danger)' };
  else if (statusVisita === 'cancelada')    statusBadge = { label:'🚫 Cancelada',     color:'#999' };
  else if (isPendente)                      statusBadge = { label:'⏳ Pendente',       color:'var(--warn)' };

  // Mostrar botões de ação apenas para planejadas sem status confirmado
  var showActions = isPlanejada && !statusVisita;

  return (
    <div style={{
      display:"flex", flexDirection:"column", gap:0,
      background:bgExtra, border:borderStyle, borderRadius:"var(--r-md)",
      overflow:"hidden", transition:"border 150ms",
    }}>
      {/* Linha principal — clicável para editar */}
      <div style={{
        display:"flex", gap:14, alignItems:"flex-start", padding:"14px 16px",
        cursor:"pointer",
      }}
        onMouseEnter={function(e){ e.currentTarget.parentElement.style.borderColor = cor; }}
        onMouseLeave={function(e){ e.currentTarget.parentElement.style.borderColor = isPendente ? 'var(--warn)' : (isPlanejada && !statusVisita ? 'var(--border)' : (statusVisita === 'realizada' ? 'var(--ok)' : 'var(--border)')); }}
        onClick={onEdit}
      >
        {/* Hora */}
        <div style={{ width:56, textAlign:"center", flexShrink:0, borderRight:"1px solid var(--border)", paddingRight:14 }}>
          <div style={{ font:"500 22px/1 var(--ff-mono)", color:"var(--tx)" }}>{time}</div>
          <div style={{ font:"400 10px/1 var(--ff-mono)", color:"var(--tx-3)", marginTop:4 }}>{evt.duracao}</div>
        </div>
        {/* Ícone tipo */}
        <div style={{ width:36, height:36, borderRadius:"var(--r-md)", background:cor+"18",
          display:"grid", placeItems:"center", flexShrink:0, position:'relative' }}>
          <i data-lucide={ic} style={{ width:17, height:17, color:cor }}></i>
          {isPlanejada && (
            <span title="Criado pelo Planejador" style={{
              position:'absolute', top:-4, right:-4,
              width:14, height:14, borderRadius:'50%',
              background:'var(--info)', border:'1px solid var(--surface)',
              display:'grid', placeItems:'center',
            }}>
              <i data-lucide="calendar-range" style={{ width:8, height:8, color:'#fff' }}></i>
            </span>
          )}
        </div>
        {/* Conteúdo */}
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ display:"flex", justifyContent:"space-between", alignItems:"flex-start", gap:10, flexWrap:"wrap" }}>
            <div style={{ font:"600 14px/1.3 var(--ff-body)", color:"var(--tx)" }}>{evt.titulo}</div>
            <div style={{ display:"flex", gap:6, alignItems:"center", flexShrink:0 }}>
              {synced && (
                <span title="Sincronizado com Outlook">
                  <i data-lucide="calendar-check" style={{ width:12, height:12, color:"var(--ok)" }}></i>
                </span>
              )}
              {statusBadge && (
                <span style={{ font:"600 9px/1 var(--ff-body)", color:statusBadge.color,
                  background:statusBadge.color+'18', padding:"4px 8px", borderRadius:"var(--r-pill)" }}>
                  {statusBadge.label}
                </span>
              )}
              <span style={{ font:"600 9px/1 var(--ff-body)", textTransform:"uppercase", letterSpacing:".07em",
                color:cor, background:cor+"15", padding:"4px 8px", borderRadius:"var(--r-pill)" }}>
                {TIPO_LABEL[evt.tipo]}
              </span>
            </div>
          </div>
          <div style={{ font:"400 11px/1.4 var(--ff-mono)", color:"var(--tx-3)", marginTop:6, display:"flex", gap:12, flexWrap:"wrap" }}>
            {cli && <span style={{ display:"flex", alignItems:"center", gap:4 }}>
              <i data-lucide="building-2" style={{ width:11, height:11 }}></i>
              {(cli.razao||'').split(" ").slice(0,3).join(" ")}
            </span>}
            {evt.local && <span style={{ display:"flex", alignItems:"center", gap:4 }}>
              <i data-lucide="map-pin" style={{ width:11, height:11 }}></i>
              {evt.local}
            </span>}
            {vend && <span style={{ display:"flex", alignItems:"center", gap:4 }}>
              <i data-lucide="user" style={{ width:11, height:11 }}></i>
              {(vend.nome||'').split(" ")[0]}
            </span>}
            {evt.op_id && <span style={{ color:"var(--info)" }}>{evt.op_id}</span>}
          </div>
        </div>
        <i data-lucide="chevron-right" style={{ width:16, height:16, color:"var(--tx-3)", flexShrink:0, marginTop:10 }}></i>
      </div>

      {/* Barra de ações — apenas para planejadas sem status */}
      {showActions && (
        <div style={{
          display:"flex", gap:8, padding:"8px 14px 10px",
          borderTop:"1px solid var(--border)",
          background: isPendente ? "#fff8e6" : "var(--surface-2)",
        }}
          onClick={function(e){ e.stopPropagation(); }}
        >
          {isPendente && (
            <span style={{ font:"400 11px/1.4 var(--ff-body)", color:"var(--warn)", flex:1, alignSelf:'center' }}>
              ⏳ Visita pendente de registro
            </span>
          )}
          <div style={{ display:"flex", gap:8, marginLeft:'auto', flexShrink:0 }}>
            {isPast ? (
              <button className="btn" style={{ fontSize:11, padding:'4px 10px', background:'var(--ok)', color:'#fff', border:'none' }}
                onClick={function(e){ e.stopPropagation(); onRealizar && onRealizar(); }}>
                ✅ Realizar
              </button>
            ) : (
              <button className="btn btn-secondary" style={{ fontSize:11, padding:'4px 10px' }}
                onClick={function(e){ e.stopPropagation(); onCancelar && onCancelar(); }}>
                🚫 Cancelar
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
