/* global React,
   IconChart, IconSearch, IconCalendar, IconInbox, IconUsers, IconLogout, IconSidebar, IconPlug,
   PipelineView, AnalyticsView, CallsView, IntegracionesView, Drawer, LoginScreen, UsersView, Avatar */
// REVOLVR CRM — shell. Auth + roles + switch de pipeline por closer + vistas + drawer.

const { useState, useEffect, useRef } = React;

// Supabase usa snake_case; el CRM usa camelCase. Convertidor de filas.
function dbLeadToCRM(row) {
  return {
    id:          row.id,
    name:        row.name,
    email:       row.email,
    phone:       row.phone || "",
    location:    row.location || "",
    timezone:    row.timezone || "",
    eventType:   row.event_type || "",
    duration:    row.duration || 30,
    scheduledAt: row.scheduled_at ? new Date(row.scheduled_at) : new Date(),
    closerId:    row.closer_id || "",
    stage:       row.stage || "agendada",
    status:      row.status || "agendada",
    meetingLink: row.meeting_link || "",
    form:        row.form_data || {},
    utm:         row.utm || { source: "", medium: "", campaign: "" },
    value:       Number(row.value) || 0,
    notes:       row.notes || [],
    history:     row.history || [],
    source:      row.source || "manual",
    createdAt:   row.created_at ? new Date(row.created_at) : new Date(),
  };
}

function CRMApp({ theme = "atrio" }) {
  const D = window.REVOLVR_DATA;
  const [currentUser, setCurrentUser] = useState(() => {
    try {
      const saved = localStorage.getItem("crm_session");
      if (!saved) return null;
      const u = JSON.parse(saved);
      // Verificar que el usuario sigue existiendo en REVOLVR_DATA
      const valid = window.REVOLVR_DATA.USERS.find((x) => x.id === u.id && x.active);
      return valid ? u : null;
    } catch { return null; }
  });

  const handleLogin = (u) => {
    localStorage.setItem("crm_session", JSON.stringify(u));
    setCurrentUser(u);
  };

  const handleLogout = () => {
    localStorage.removeItem("crm_session");
    setCurrentUser(null);
  };

  if (!currentUser) {
    return (
      <div className="crm-root" data-theme={theme}>
        <LoginScreen onLogin={handleLogin}/>
      </div>);
  }
  return <CRMShell theme={theme} currentUser={currentUser} onLogout={handleLogout}/>;
}

function CRMShell({ theme, currentUser, onLogout }) {
  const D = window.REVOLVR_DATA;
  const isAdmin = currentUser.role === "admin";

  const [tab, setTab] = useState("pipeline");
  const [stages, setStages] = useState(() => D.STAGES.map((s) => ({ ...s })));
  const [calls, setCalls] = useState([]);  // Supabase carga los leads — data.js solo es fallback
  const [loadingLeads, setLoadingLeads] = useState(false);
  const [users, setUsers] = useState([]);
  const [closers, setClosers] = useState([]);
  const [openId, setOpenId] = useState(null);
  const [filters, setFilters] = useState({ source: null, q: "", dateRange: null });
  const [activeCloser, setActiveCloser] = useState(isAdmin ? "all" : currentUser.closerId);
  const [adSpend, setAdSpend] = useState(() => ({ ...D.AD_SPEND }));
  const [justMovedId, setJustMovedId] = useState(null);
  const justMovedTimer = useRef(null);
  const [toasts, setToasts] = useState([]);
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const [userMenu, setUserMenu] = useState(false);
  const userMenuRef = useRef(null);

  useEffect(() => {
    if (!userMenu) return;
    const onDown = (e) => { if (userMenuRef.current && !userMenuRef.current.contains(e.target)) setUserMenu(false); };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [userMenu]);

  // Carga leads y usuarios reales desde Supabase al montar
  useEffect(() => {
    if (!window.SUPABASE) return;
    setLoadingLeads(true);
    // Cargar leads
    window.SUPABASE.from("leads").select("*").order("scheduled_at", { ascending: false })
      .then(({ data, error }) => {
        if (!error && data && data.length > 0) setCalls(data.map(dbLeadToCRM));
        setLoadingLeads(false);
      });
    // Cargar usuarios
    window.SUPABASE.from("crm_users").select("*").order("created_at")
      .then(({ data, error }) => {
        if (!error && data && data.length > 0) {
          setUsers(data.map((u) => ({ id: u.id, name: u.name, email: u.email, password: u.password, role: u.role, closerId: u.closer_id, active: u.active, lastLogin: u.last_login || "" })));
        }
      });
    // Cargar closers
    window.SUPABASE.from("closers").select("*").order("order_index")
      .then(({ data, error }) => {
        if (!error && data) {
          setClosers(data.map((c) => ({ id: c.id, name: c.name, initials: c.initials, color: c.color })));
        }
      });
  }, []);

  const viewCloser = isAdmin ? activeCloser : currentUser.closerId;
  const globalScope = isAdmin && viewCloser === "all";
  const visibleCalls = calls.filter((c) => viewCloser === "all" ? true : c.closerId === viewCloser);

  const pushToast = (text, kind = "ok") => {
    const id = Math.random().toString(36).slice(2);
    setToasts((t) => [...t, { id, text, kind }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 4000);
  };

  const handleOpen = (id) => setOpenId(id);

  const handleMove = (id, newStage, beforeId) => {
    setCalls((cs) => {
      const moving = cs.find((c) => c.id === id);
      if (!moving) return cs;
      const sameStage = moving.stage === newStage;
      const fromLabel = stages.find((s) => s.id === moving.stage)?.label;
      const toLabel = stages.find((s) => s.id === newStage)?.label;
      const statusMap = { asistio: "asistio", noshow: "noshow", confirmada: "confirmada", agendada: "agendada" };
      const status = sameStage ? moving.status : (statusMap[newStage] || moving.status);
      const updated = sameStage ? { ...moving } : {
        ...moving, stage: newStage, status,
        history: [{ ts: "ahora", kind: "stage", e: "Etapa cambiada", det: `${fromLabel} → ${toLabel}` }, ...moving.history],
      };
      const rest = cs.filter((c) => c.id !== id);
      let idx;
      if (beforeId) {
        idx = rest.findIndex((c) => c.id === beforeId);
        if (idx < 0) idx = rest.length;
      } else {
        // sin destino explícito: colócalo después de la última tarjeta de esa etapa
        let last = -1;
        rest.forEach((c, i) => { if (c.stage === newStage) last = i; });
        idx = last + 1;
      }
      rest.splice(idx, 0, updated);
      return rest;
    });
    setJustMovedId(id);
    if (justMovedTimer.current) clearTimeout(justMovedTimer.current);
    justMovedTimer.current = setTimeout(() => setJustMovedId(null), 600);

    if (window.SUPABASE) {
      const statusMap = { asistio: "asistio", noshow: "noshow", confirmada: "confirmada", agendada: "agendada", propuesta: "asistio", ganada: "asistio", perdida: "asistio" };
      window.SUPABASE.from("leads")
        .update({ stage: newStage, status: statusMap[newStage] || newStage })
        .eq("id", id)
        .then(({ error }) => { if (error) console.error("Error guardando etapa:", error); });
    }
  };
  const handleChangeStage = handleMove;

  const handleChangeCloser = (id, closerId) => {
    setCalls((cs) => cs.map((c) => {
      if (c.id !== id) return c;
      const to = closers.find((x) => x.id === closerId)?.name;
      return { ...c, closerId, history: [{ ts: "ahora", kind: "note", e: "Llamada reasignada", det: `a ${to}` }, ...c.history] };
    }));
    pushToast("Llamada reasignada");
  };

  const handleAddNote = (id, body) => {
    const newNote = { ts: "ahora", who: currentUser.name, body };
    const newHistEntry = { ts: "ahora", kind: "note", e: "Nota agregada", det: `por ${currentUser.name}` };

    setCalls((cs) => cs.map((c) => c.id !== id ? c : {
      ...c,
      notes: [newNote, ...c.notes],
      history: [newHistEntry, ...c.history],
    }));

    if (window.SUPABASE) {
      const lead = calls.find((c) => c.id === id);
      const updatedNotes = lead ? [newNote, ...lead.notes] : [newNote];
      const updatedHistory = lead ? [newHistEntry, ...lead.history] : [newHistEntry];
      window.SUPABASE.from("leads")
        .update({ notes: updatedNotes, history: updatedHistory })
        .eq("id", id)
        .then(({ error }) => { if (error) console.error("Error guardando nota:", error); });
    }
  };

  const handleEditNote = (id, noteIndex, newBody) => {
    setCalls((cs) => cs.map((c) => {
      if (c.id !== id) return c;
      const updatedNotes = c.notes.map((n, i) => i === noteIndex ? { ...n, body: newBody, ts: "editada" } : n);
      if (window.SUPABASE) {
        window.SUPABASE.from("leads").update({ notes: updatedNotes }).eq("id", id)
          .then(({ error }) => { if (error) console.error("Error editando nota:", error); });
      }
      return { ...c, notes: updatedNotes };
    }));
  };

  const handleDeleteNote = (id, noteIndex) => {
    setCalls((cs) => cs.map((c) => {
      if (c.id !== id) return c;
      const updatedNotes = c.notes.filter((_, i) => i !== noteIndex);
      if (window.SUPABASE) {
        window.SUPABASE.from("leads").update({ notes: updatedNotes }).eq("id", id)
          .then(({ error }) => { if (error) console.error("Error borrando nota:", error); });
      }
      return { ...c, notes: updatedNotes };
    }));
    pushToast("Nota eliminada");
  };

  const handleUpdateSale = (id, sale) => {
    setCalls((cs) => cs.map((c) => c.id !== id ? c : {
      ...c, sale,
      history: [{ ts: "ahora", kind: "stage", e: "Venta registrada", det: `${sale.programa} · $${(sale.total || 0).toLocaleString("en-US")} · ${sale.tipo === "total" ? "pago total" : "abono"}` }, ...c.history],
    }));
    pushToast("Venta actualizada");
  };

  // Stage CRUD
  const handleAddStage = (label, color) => setStages((sx) => [...sx, { id: "s_" + Date.now(), label, color }]);
  const handleRenameStage = (id, label) => setStages((sx) => sx.map((s) => s.id === id ? { ...s, label } : s));
  const handleRecolorStage = (id, color) => setStages((sx) => sx.map((s) => s.id === id ? { ...s, color } : s));
  const handleMoveStage = (id, dir) => setStages((sx) => {
    const i = sx.findIndex((s) => s.id === id); const n = i + dir;
    if (i < 0 || n < 0 || n >= sx.length) return sx;
    const out = sx.slice(); [out[i], out[n]] = [out[n], out[i]]; return out;
  });
  const handleReorderStages = (fromId, toId) => setStages((sx) => {
    const f = sx.findIndex((s) => s.id === fromId), t = sx.findIndex((s) => s.id === toId);
    if (f < 0 || t < 0 || f === t) return sx;
    const out = sx.slice(); const [m] = out.splice(f, 1); out.splice(t, 0, m); return out;
  });
  const handleDeleteStage = (id, moveTo) => {
    if (moveTo) setCalls((cs) => cs.map((c) => c.stage === id ? { ...c, stage: moveTo } : c));
    setStages((sx) => sx.filter((s) => s.id !== id));
  };

  const handleExport = (rows) => {
    const headers = ["nombre", "email", "telefono", "ubicacion", "evento", "fecha", "closer", "etapa", "estado", "fuente", "campaña", "facturacion"];
    const data = rows.map((c) => [
      c.name, c.email, c.phone, c.location, c.eventType,
      c.scheduledAt instanceof Date ? c.scheduledAt.toLocaleString("es-ES") : "",
      closers.find((x) => x.id === c.closerId)?.name || "", c.stage, c.status,
      c.utm.source, c.utm.campaign, c.form.facturacion,
    ]);
    const esc = (v) => `"${String(v == null ? "" : v).replace(/"/g, '""')}"`;
    const csv = [headers, ...data].map((r) => r.map(esc).join(",")).join("\n");
    const blob = new Blob(["\uFEFF" + csv], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a"); a.href = url;
    a.download = `llamadas_${new Date().toISOString().slice(0, 10)}.csv`;
    document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
    pushToast(`${rows.length} llamadas exportadas`);
  };

  const handleAddUser = (u) => {
    const newId = "u_" + Date.now();
    let closerId = u.closerId;
    if (u.role === "closer" && u.closerId === "new") {
      closerId = "c_" + Date.now();
      const newCloser = { id: closerId, name: u.name, initials: u.name.split(" ").map((s) => s[0]).slice(0, 2).join("").toUpperCase(), color: "#0e7a9a" };
      setClosers((cs) => [...cs, newCloser]);
      if (window.SUPABASE) {
        window.SUPABASE.from("closers").insert({ id: closerId, name: u.name, initials: newCloser.initials, color: "#0e7a9a", active: true, order_index: D.CLOSERS.length })
          .then(({ error }) => { if (error) console.error("Error guardando closer:", error); });
      }
    }
    const newUser = { id: newId, name: u.name, email: u.email, password: u.password, role: u.role, closerId: u.role === "admin" ? null : closerId, active: true, lastLogin: "nunca" };
    setUsers((us) => [...us, newUser]);
    if (window.SUPABASE) {
      window.SUPABASE.from("crm_users").insert({ id: newId, name: u.name, email: u.email, password: u.password, role: u.role, closer_id: u.role === "admin" ? null : closerId, active: true })
        .then(({ error }) => { if (error) console.error("Error guardando usuario:", error); });
    }
    pushToast("Usuario creado");
  };

  const handleToggleActive = (id) => {
    setUsers((us) => us.map((u) => u.id === id ? { ...u, active: !u.active } : u));
    const u = users.find((x) => x.id === id);
    if (window.SUPABASE && u) {
      window.SUPABASE.from("crm_users").update({ active: !u.active }).eq("id", id)
        .then(({ error }) => { if (error) console.error("Error actualizando usuario:", error); });
    }
  };

  const handleResetPassword = (id, newPassword) => {
    setUsers((us) => us.map((u) => u.id === id ? { ...u, password: newPassword } : u));
    if (window.SUPABASE) {
      window.SUPABASE.from("crm_users").update({ password: newPassword }).eq("id", id)
        .then(({ error }) => { if (error) console.error("Error reseteando contraseña:", error); });
    }
    pushToast("Contraseña actualizada");
  };

  const handleDeleteUser = (id) => {
    setUsers((us) => us.filter((u) => u.id !== id));
    if (window.SUPABASE) {
      window.SUPABASE.from("crm_users").delete().eq("id", id)
        .then(({ error }) => { if (error) console.error("Error eliminando usuario:", error); });
    }
    pushToast("Usuario eliminado");
  };

  const open = calls.find((c) => c.id === openId);
  const counts = D.countByStage(visibleCalls);
  const closer = closers.find((x) => x.id === currentUser.closerId);

  const pageTitle = tab === "pipeline" ? "Pipeline" : tab === "llamadas" ? "Próximas llamadas" : tab === "analitica" ? "Analítica" : tab === "integraciones" ? "Integraciones" : "Usuarios";

  return (
    <div className="crm-root" data-theme={theme} data-sidebar-collapsed={sidebarCollapsed ? "true" : undefined}>
      {/* Sidebar */}
      <aside className="crm-side">
        <div className="crm-side-collapsed-mark">R</div>
        <div className="crm-brand">
          <img src="assets/revolvr-logo.png" alt="REVOLVR" className="crm-brand-logo"/>
          <div className="crm-brand-name">CRM · Llamadas</div>
        </div>

        <nav className="crm-nav">
          <div className="crm-nav-section">Workspace</div>
          <NavItem icon={<IconInbox size={14}/>} active={tab === "pipeline"} onClick={() => setTab("pipeline")} badge={visibleCalls.length}>Pipeline</NavItem>
          <NavItem icon={<IconCalendar size={14}/>} active={tab === "llamadas"} onClick={() => setTab("llamadas")} badge={visibleCalls.filter((c) => ["agendada", "confirmada"].includes(c.status)).length}>Próximas llamadas</NavItem>
          <NavItem icon={<IconChart size={14}/>} active={tab === "analitica"} onClick={() => setTab("analitica")}>Analítica</NavItem>
          {isAdmin &&
            <>
              <div className="crm-nav-section">Administración</div>
              <NavItem icon={<IconUsers size={14}/>} active={tab === "usuarios"} onClick={() => setTab("usuarios")} badge={users.length}>Usuarios</NavItem>
              <NavItem icon={<IconPlug size={14}/>} active={tab === "integraciones"} onClick={() => setTab("integraciones")}>Integraciones</NavItem>
            </>}
        </nav>

        {/* Switch de pipeline por closer */}
        <div className="crm-pipes">
          <div className="crm-pipes-h">{isAdmin ? "Pipelines por closer" : "Tu pipeline"}</div>
          {isAdmin &&
            <button className="crm-pipe" data-active={activeCloser === "all" ? "true" : undefined} onClick={() => setActiveCloser("all")}>
              <span className="pipe-all">∗</span><span className="pipe-name">Todos los closers</span>
              <span className="pipe-n">{calls.length}</span>
            </button>}
          {(isAdmin ? closers : closers.filter((c) => c.id === currentUser.closerId)).map((c) => (
            <button key={c.id} className="crm-pipe" data-active={viewCloser === c.id ? "true" : undefined}
                    onClick={() => isAdmin && setActiveCloser(c.id)} style={!isAdmin ? { cursor: "default" } : undefined}>
              <span className="rv-avatar xs" style={{ background: c.color }}>{c.initials}</span>
              <span className="pipe-name">{c.name}</span>
              <span className="pipe-n">{calls.filter((x) => x.closerId === c.id).length}</span>
            </button>
          ))}
        </div>
      </aside>

      {/* Main */}
      <div className="crm-main">
        <div className="crm-topbar">
          <button className="sidebar-toggle" onClick={() => setSidebarCollapsed((v) => !v)} title="Menú"><IconSidebar size={15}/></button>
          <div className="crm-page-title">
            <span className="crumb">REVOLVR</span><span className="sep">/</span><span>{pageTitle}</span>
            {tab !== "usuarios" && tab !== "integraciones" && isAdmin && <span className="scope-tag">{viewCloser === "all" ? "Todos" : closers.find((c) => c.id === viewCloser)?.name}</span>}
          </div>
          {tab !== "usuarios" && tab !== "integraciones" &&
            <div className="crm-search">
              <IconSearch size={13} className="ic-search"/>
              <input value={filters.q} onChange={(e) => setFilters({ ...filters, q: e.target.value })} placeholder="Buscar nombre, email, industria…"/>
            </div>}

          {/* User menu */}
          <div className="user-menu" ref={userMenuRef} style={{ marginLeft: (tab === "usuarios" || tab === "integraciones") ? "auto" : 0 }}>
            <button className="user-btn" onClick={() => setUserMenu((v) => !v)}>
              <Avatar name={currentUser.name} color={isAdmin ? "#0d1419" : (closer ? closer.color : "var(--accent)")} size={30}/>
              <div className="ub-meta">
                <div className="ub-name">{currentUser.name.split(" ")[0]}</div>
                <div className="ub-role">{isAdmin ? "Admin" : "Closer"}</div>
              </div>
            </button>
            {userMenu &&
              <div className="user-pop">
                <div className="up-head">
                  <Avatar name={currentUser.name} color={isAdmin ? "#0d1419" : (closer ? closer.color : "var(--accent)")} size={36}/>
                  <div><div className="up-name">{currentUser.name}</div><div className="up-email">{currentUser.email}</div></div>
                </div>
                <span className="role-pill" data-role={currentUser.role} style={{ margin: "8px 12px" }}>{isAdmin ? "Administrador" : "Closer"}</span>
                <hr/>
                <button className="up-item" onClick={onLogout}><IconLogout size={14}/> Cerrar sesión</button>
              </div>}
          </div>
        </div>

        <div className="crm-content" style={{ position: "relative" }}>
          {loadingLeads && (
            <div style={{
              position: "absolute", top: 0, left: 0, right: 0,
              height: 3, background: "var(--accent)",
              animation: "progress-bar 1.5s ease infinite", zIndex: 5,
            }}/>
          )}
          {tab === "pipeline" &&
            <PipelineView calls={visibleCalls} stages={stages} filters={filters} setFilters={setFilters} showCloser={viewCloser === "all"} justMovedId={justMovedId}
              onOpen={handleOpen} onMove={handleMove} onExport={handleExport}
              onAddStage={handleAddStage} onRenameStage={handleRenameStage} onRecolorStage={handleRecolorStage}
              onDeleteStage={handleDeleteStage} onMoveStage={handleMoveStage} onReorderStages={handleReorderStages}/>}
          {tab === "llamadas" && <CallsView calls={visibleCalls} closers={closers} onOpen={handleOpen}/>}
          {tab === "analitica" && <AnalyticsView calls={visibleCalls} allCalls={calls} closers={closers} isAdmin={currentUser.role === "admin"}
              adSpend={adSpend} onEditSpend={setAdSpend} canEditSpend={currentUser.role === "admin"}
              filters={filters} setFilters={setFilters}
              accent={getComputedStyle(document.documentElement).getPropertyValue("--accent") || "#0e7a9a"}/>}
          {tab === "usuarios" && isAdmin && <UsersView users={users} onAddUser={handleAddUser} onToggleActive={handleToggleActive} onDeleteUser={handleDeleteUser} onResetPassword={handleResetPassword} currentUser={currentUser}/>}
          {tab === "integraciones" && isAdmin && <IntegracionesView closers={closers} pushToast={pushToast}/>}
        </div>
      </div>

      {open &&
        <Drawer c={open} stages={stages} closers={closers} onClose={() => setOpenId(null)}
          onChangeStage={handleChangeStage} onChangeCloser={handleChangeCloser} onAddNote={handleAddNote} onEditNote={handleEditNote} onDeleteNote={handleDeleteNote} onUpdateSale={handleUpdateSale}/>}

      <div className="toast-stack">
        {toasts.map((t) => (
          <div className="toast system" key={t.id} data-kind={t.kind}>
            <div className="t-body"><div className="t-msg" style={{ fontWeight: 500 }}>{t.text}</div></div>
            <button onClick={() => setToasts((x) => x.filter((y) => y.id !== t.id))}>×</button>
          </div>
        ))}
      </div>
    </div>);
}

function NavItem({ icon, children, active, onClick, badge }) {
  return (
    <button className="crm-nav-item" data-active={active ? "true" : undefined} onClick={onClick}>
      <span className="ic">{icon}</span><span>{children}</span>
      {(badge != null && badge !== 0) && <span className="badge">{badge}</span>}
    </button>);
}

window.CRMApp = CRMApp;
