// Top-level App — sidebar nav + data fetch + dial action

const TABS = [
  { id: "overview", label: "Panel general", icon: "Dashboard" },
  { id: "patients", label: "Pacientes", icon: "Users" },
  { id: "interactions", label: "Llamadas", icon: "Phone" },
  { id: "schedule", label: "Programación", icon: "Calendar" },
  { id: "equipment", label: "Equipos", icon: "Box" },
];

// ── Agent phone (sidebar) ─────────────────────────────────────────────────
function AgentPhone() {
  const [phone, setPhone] = React.useState(null);

  React.useEffect(() => {
    fetch(`${CLARA_API}/api/phones`).then(r => r.json()).then(d => {
      const phones = d.phones || d || [];
      if (phones.length > 0) setPhone(phones[0]);
    }).catch(() => {});
  }, []);

  if (!phone) return null;

  const num = phone.number || phone.phoneNumber || "";
  const fmt = num.replace(/(\+\d)(\d{3})(\d{3})(\d{4})/, "$1 ($2) $3-$4");

  return (
    <div className="mt-2 pt-2 border-t border-white/5 flex items-center gap-1.5">
      <I.Phone size={10} className="text-ink-500" />
      <span className="text-[11px] font-mono text-ink-400">{fmt}</span>
    </div>
  );
}

// ── Balance indicator (sidebar) ───────────────────────────────────────────
function BalanceIndicator() {
  const [bal, setBal] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    async function fetchBal() {
      try {
        const r = await fetch(`${CLARA_API}/api/twilio/balance`);
        const d = await r.json();
        if (!cancelled && d.success) setBal(d);
      } catch {}
    }
    fetchBal();
    const id = setInterval(fetchBal, 60000);
    return () => { cancelled = true; clearInterval(id); };
  }, []);

  if (!bal) return null;

  const v = parseFloat(bal.balance);
  const color = v > 5 ? "text-emerald-400" : v > 2 ? "text-amber-300" : "text-rose-300";

  return (
    <div className="hidden md:flex items-center gap-1.5 text-[11px] font-mono pr-3 mr-1 border-r border-white/5">
      <span className={`${color}`}>${v.toFixed(2)}</span>
      <span className="text-ink-600">{bal.currency}</span>
    </div>
  );
}

// (Coordinator config removed — no longer used)

function App() {
  const [data, setData] = React.useState({ patients: [], interactions: [], escalations: [], equipmentTypes: [] });
  const [loading, setLoading] = React.useState(true);
  const [tab, setTab] = React.useState("overview");
  const [selectedPatient, setSelectedPatient] = React.useState(null);
  const [showAdd, setShowAdd] = React.useState(false);
  const [toasts, setToasts] = React.useState([]);
  const [now, setNow] = React.useState(new Date());
  const [agentStatus, setAgentStatus] = React.useState({ connected: true, lastSync: new Date() });
  const [refreshKey, setRefreshKey] = React.useState(0);

  // Call system — WebSocket + floating windows
  const callManager = useCallManager();

  // Fetch data from API + auto refresh every 5s
  React.useEffect(() => {
    let cancelled = false;
    async function load() {
      try {
        const [pRes, iRes, eRes, eqRes] = await Promise.all([
          fetch(`${CLARA_API}/api/patients`, { cache: "no-store" }),
          fetch(`${CLARA_API}/api/interactions`, { cache: "no-store" }),
          fetch(`${CLARA_API}/api/escalations`, { cache: "no-store" }),
          fetch(`${CLARA_API}/api/equipment`, { cache: "no-store" }),
        ]);
        if (!pRes.ok || !iRes.ok || !eRes.ok || !eqRes.ok) throw new Error("API error");
        const [pData, iData, eData, eqData] = await Promise.all([
          pRes.json(), iRes.json(), eRes.json(), eqRes.json(),
        ]);
        if (cancelled) return;
        setData({
          patients: pData.patients || [],
          interactions: iData.interactions || [],
          escalations: eData.escalations || [],
          equipmentTypes: eqData.equipmentTypes || [],
        });
        setAgentStatus({ connected: true, lastSync: new Date() });
      } catch (err) {
        if (!cancelled) setAgentStatus((s) => ({ ...s, connected: false }));
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    load();
    const id = setInterval(load, 5000);
    return () => { cancelled = true; clearInterval(id); };
  }, [refreshKey]);

  // Keep selectedPatient in sync with data
  React.useEffect(() => {
    if (selectedPatient) {
      const updated = (data.patients || []).find((p) => p.id === selectedPatient.id);
      if (updated && JSON.stringify(updated) !== JSON.stringify(selectedPatient)) {
        setSelectedPatient(updated);
      }
    }
  }, [data]);

  // Clock tick
  React.useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 30 * 1000);
    return () => clearInterval(id);
  }, []);

  const pushToast = (t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((arr) => [...arr, { ...t, id }]);
    setTimeout(() => setToasts((arr) => arr.filter((x) => x.id !== id)), 5000);
  };

  // Dial — POST to local agent API; gracefully fall back to a simulated success
  // when the local server isn't reachable (so the prototype is demonstrable).
  const handleCall = async (patient) => {
    const greeting = `${getMadridGreeting()}, soy Clara de Oximesa, servicio de equipos médicos. ¿Hablo con ${patient.name.split(" ")[0]}?`;
    const body = {
      to: patient.phone,
      from: "+14258423349",
      greeting,
      metadata: {
        patientId: patient.id,
        patientName: patient.name,
        priority: patient.priority,
        equipmentType: patient.equipmentType,
      },
    };
    try {
      const r = await fetch(`${CLARA_API}/api/dial`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
        // Short timeout via AbortController
      });
      if (!r.ok) throw new Error("HTTP " + r.status);
      pushToast({ tone: "success", title: `Llamada lanzada a ${patient.name.split(" ")[0]}`, body: `Clara marcando ${patient.phone}` });
      // The call window will appear automatically via WebSocket call.started event
    } catch (err) {
      pushToast({
        tone: "info",
        title: `Llamada en cola para ${patient.name.split(" ")[0]}`,
        body: `(Modo demo — POST ${CLARA_API}/api/dial no disponible)\n${greeting}`,
      });
    }
    return true;
  };

  const handleCreatePatient = async (p) => {
    try {
      await fetch(`${CLARA_API}/api/patients`, {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify(p),
      });
    } catch {}
    setData((d) => ({ ...d, patients: [...d.patients, p] }));
    pushToast({ tone: "success", title: `${p.name} dado de alta`, body: `${p.id} · ${p.equipmentType}` });
    setShowAdd(false);
  };

  const handleDeletePatient = async (patientId) => {
    try {
      const r = await fetch(`${CLARA_API}/api/patients/${patientId}`, { method: "DELETE" });
      if (!r.ok) throw new Error("HTTP " + r.status);
      setData((d) => ({ ...d, patients: d.patients.filter((p) => p.id !== patientId) }));
      setSelectedPatient(null);
      pushToast({ tone: "success", title: "Paciente eliminado" });
    } catch (err) {
      pushToast({ tone: "error", title: "Error al eliminar", body: err.message });
    }
  };

  const handleResolveEscalation = async (escalationId) => {
    try {
      const r = await fetch(`${CLARA_API}/api/escalations/${escalationId}/resolve`, { method: "PATCH" });
      if (!r.ok) throw new Error("HTTP " + r.status);
      // Update local state
      setData((d) => ({
        ...d,
        escalations: d.escalations.map((e) =>
          e.id === escalationId ? { ...e, status: "resolved", resolvedDate: new Date().toISOString() } : e
        ),
      }));
      pushToast({ tone: "success", title: "Escalación resuelta", body: `${escalationId} marcada como resuelta` });
    } catch (err) {
      pushToast({ tone: "error", title: "Error", body: "No se pudo resolver la escalación" });
    }
  };

  const goTab = (id) => {
    setTab(id);
    setSelectedPatient(null);
  };

  return (
    <div className="h-screen flex bg-ink-950 text-ink-100 overflow-hidden" data-screen-label="Oximesa Dashboard">
      {/* Sidebar */}
      <aside className="hidden md:flex w-60 shrink-0 flex-col border-r border-white/5 bg-ink-900/60 backdrop-blur-sm h-screen sticky top-0">
        <div className="px-5 py-5 flex items-center gap-2.5 border-b border-white/5">
          <span className="w-8 h-8 rounded-lg bg-sky-500/15 text-sky-300 inline-flex items-center justify-center">
            <I.Logo size={18} />
          </span>
          <div className="flex flex-col leading-tight">
            <span className="text-sm font-semibold tracking-tight text-ink-100">Oximesa</span>
            <span className="text-[10px] text-ink-500 uppercase tracking-wider">Equipos médicos</span>
          </div>
        </div>

        <nav className="flex-1 py-3 flex flex-col">
          <div className="px-5 pb-1.5 text-[10px] uppercase tracking-wider text-ink-500 font-semibold">Operación</div>
          {TABS.map((t) => {
            const Icn = I[t.icon];
            const active = tab === t.id;
            const count = ({
              patients: data.patients?.length,
              interactions: data.interactions?.length,
              escalations: data.escalations?.filter((e) => e.status === "pending").length,
            })[t.id];
            return (
              <button
                key={t.id}
                onClick={() => goTab(t.id)}
                className={`w-full text-left px-5 py-2 flex items-center gap-2.5 text-sm transition-colors ${
                  active ? "nav-active text-ink-100" : "text-ink-400 hover:text-ink-100 hover:bg-white/3"
                }`}
              >
                <Icn size={15} />
                <span className="flex-1">{t.label}</span>
                {count != null && count > 0 && (
                  <span className={`text-[10px] font-mono tabular-nums px-1.5 py-0.5 rounded ${
                    active ? "bg-sky-500/15 text-sky-200" : "bg-white/5 text-ink-400"
                  }`}>{count}</span>
                )}
              </button>
            );
          })}

          <div className="mt-6 px-5 pb-1.5 text-[10px] uppercase tracking-wider text-ink-500 font-semibold">Acciones</div>
          <button
            onClick={() => setShowAdd(true)}
            className="w-full text-left px-5 py-2 flex items-center gap-2.5 text-sm text-ink-300 hover:text-ink-100 hover:bg-white/3"
          >
            <I.Plus size={15} /> Nuevo paciente
          </button>
        </nav>

        {/* Agent status footer */}
        <div className="px-4 py-4 border-t border-white/5 mx-1 mb-1">
          <div className="rounded-lg bg-ink-850 border border-white/5 p-3">
            <div className="flex items-center gap-2">
              <span className={`w-1.5 h-1.5 rounded-full ${callManager.wsConnected ? "bg-emerald-400 pulse-dot" : "bg-rose-400"}`}></span>
              <span className="text-xs font-medium text-ink-200">Clara</span>
              <span className="ml-auto text-[10px] font-mono text-ink-500">v2.0</span>
            </div>
            <div className="text-[11px] text-ink-500 mt-1.5">
              {callManager.wsConnected
                ? <>Operativa · SSE conectado{Object.values(callManager.calls).filter(c => c.status === "active").length > 0
                    ? <> · <span className="text-emerald-300">{Object.values(callManager.calls).filter(c => c.status === "active").length} llamada{Object.values(callManager.calls).filter(c => c.status === "active").length > 1 ? "s" : ""}</span></>
                    : ""}</>
                : <>Sin conexión con backend</>}
            </div>
            <AgentPhone />
          </div>
        </div>
      </aside>

      <div className="flex-1 flex flex-col min-w-0 h-screen overflow-y-auto">
        {/* Header */}
        <header className="sticky top-0 z-20 bg-ink-950/80 backdrop-blur-md border-b border-white/5 px-6 py-3 flex items-center gap-4">
          <div className="md:hidden flex items-center gap-2">
            <span className="w-7 h-7 rounded-md bg-sky-500/15 text-sky-300 inline-flex items-center justify-center">
              <I.Logo size={14} />
            </span>
            <span className="text-sm font-semibold">Oximesa</span>
          </div>
          <div className="hidden md:block">
            <div className="text-[11px] text-ink-500 font-mono">
              {now.toLocaleDateString("es-ES", { weekday: "long", day: "numeric", month: "long", year: "numeric" })}
            </div>
          </div>
          <div className="flex-1"></div>
          <BalanceIndicator />
          <div className="text-[11px] text-ink-400 font-mono hidden md:flex items-center gap-2">
            <I.Clock size={12} /> Madrid {fmtClock(now)}
          </div>
          <button
            onClick={() => setRefreshKey((k) => k + 1)}
            className="text-ink-400 hover:text-ink-200 p-1.5 rounded-md hover:bg-white/5"
            title="Refrescar"
          >
            <I.Refresh size={14} />
          </button>
          <div className="flex items-center gap-2 pl-3 border-l border-white/5">
            <span className="w-7 h-7 rounded-full bg-sky-500/20 text-sky-200 inline-flex items-center justify-center text-xs font-semibold">O</span>
            <div className="hidden lg:flex flex-col leading-tight">
              <span className="text-xs text-ink-200 font-medium">Oximesa</span>
              <span className="text-[10px] text-ink-500">Equipos médicos</span>
            </div>
          </div>
        </header>

        {/* Content */}
        <main className="flex-1 px-6 py-6 max-w-[1400px] w-full mx-auto">
          {loading ? (
            <div className="flex items-center justify-center py-32 text-ink-500 text-sm">
              <span className="inline-flex items-center gap-2">
                <I.Refresh size={14} className="animate-spin" /> Cargando datos…
              </span>
            </div>
          ) : tab === "overview" ? (
            <OverviewView data={data} onCall={handleCall} onSelectPatient={setSelectedPatient} onGoTab={goTab} />
          ) : tab === "patients" ? (
            <PatientsView data={data} onCall={handleCall} onSelectPatient={setSelectedPatient} onAddNew={() => setShowAdd(true)} onDeletePatient={handleDeletePatient} />
          ) : tab === "interactions" ? (
            <InteractionsView data={data} onSelectPatient={setSelectedPatient} />
          ) : tab === "schedule" ? (
            <ScheduleView onCall={handleCall} onSelectPatient={setSelectedPatient} />
          ) : tab === "escalations" ? (
            <EscalationsView data={data} onSelectPatient={setSelectedPatient} onResolve={handleResolveEscalation} />
          ) : tab === "equipment" ? (
            <EquipmentView data={data} />
          ) : null}
        </main>
      </div>

      {selectedPatient && (
        <PatientPanel
          patient={selectedPatient}
          data={data}
          onClose={() => setSelectedPatient(null)}
          onCall={handleCall}
          onUpdate={() => setRefreshKey((k) => k + 1)}
          onDelete={() => handleDeletePatient(selectedPatient.id)}
        />
      )}
      {showAdd && (
        <AddPatientModal
          data={data}
          onClose={() => setShowAdd(false)}
          onCreate={handleCreatePatient}
        />
      )}
      <ToastHost toasts={toasts} onDismiss={(id) => setToasts((arr) => arr.filter((x) => x.id !== id))} />

      {/* Call system overlay — floating windows, notifications, bottom bar */}
      <CallLayer
        calls={callManager.calls}
        notifications={callManager.notifications}
        wsConnected={callManager.wsConnected}
        toggleMinimize={callManager.toggleMinimize}
        toggleMaximize={callManager.toggleMaximize}
        closeCall={callManager.closeCall}
        hangupCall={callManager.hangupCall}
        dismissNotification={callManager.dismissNotification}
        focusCall={callManager.focusCall}
      />
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
