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

// ── Login Screen ──────────────────────────────────────────────────────────────
function LoginScreen({ onLogin }) {
  const [user, setUser] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [error, setError] = React.useState("");
  const [loading, setLoading] = React.useState(false);

  async function handleSubmit(e) {
    e.preventDefault();
    setError("");
    setLoading(true);
    try {
      const r = await authFetch(`${NAFFCO_API}/api/login`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ user, password }),
      });
      const d = await r.json();
      if (d.ok && d.token) {
        setAuthToken(d.token);
        onLogin();
      } else {
        setError(d.error || "Authentication error");
      }
    } catch {
      setError("Cannot connect to server");
    }
    setLoading(false);
  }

  return (
    <div style={{
      minHeight: "100vh",
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      background: "#0a0a0f",
    }}>
      <form onSubmit={handleSubmit} style={{
        width: "340px",
        padding: "40px 32px",
        background: "rgba(255,255,255,0.02)",
        border: "1px solid rgba(255,255,255,0.06)",
        borderRadius: "16px",
      }}>
        <div style={{ textAlign: "center", marginBottom: "32px" }}>
          <div style={{ fontSize: "28px", marginBottom: "8px" }}>🔥</div>
          <div style={{ fontSize: "15px", color: "rgba(255,255,255,0.85)", letterSpacing: "0.5px" }}>Nova</div>
          <div style={{ fontSize: "11px", color: "rgba(255,255,255,0.3)", marginTop: "4px" }}>Naffco Fire Alarm Monitoring</div>
        </div>

        <div style={{ marginBottom: "16px" }}>
          <input
            type="text" placeholder="Username" value={user} onChange={e => setUser(e.target.value)} autoFocus
            style={{ width: "100%", padding: "10px 14px", background: "rgba(255,255,255,0.03)", border: "1px solid rgba(255,255,255,0.08)", borderRadius: "8px", color: "rgba(255,255,255,0.85)", fontSize: "13px", outline: "none", boxSizing: "border-box" }}
          />
        </div>
        <div style={{ marginBottom: "20px" }}>
          <input
            type="password" placeholder="Password" value={password} onChange={e => setPassword(e.target.value)}
            style={{ width: "100%", padding: "10px 14px", background: "rgba(255,255,255,0.03)", border: "1px solid rgba(255,255,255,0.08)", borderRadius: "8px", color: "rgba(255,255,255,0.85)", fontSize: "13px", outline: "none", boxSizing: "border-box" }}
          />
        </div>

        {error && <div style={{ fontSize: "12px", color: "#f87171", textAlign: "center", marginBottom: "14px" }}>{error}</div>}

        <button type="submit" disabled={loading || !user || !password}
          style={{ width: "100%", padding: "10px", background: loading ? "rgba(255,255,255,0.04)" : "rgba(245,158,11,0.15)", border: "1px solid rgba(245,158,11,0.3)", borderRadius: "8px", color: "rgba(245,158,11,0.9)", fontSize: "13px", cursor: loading ? "wait" : "pointer", transition: "all 0.15s" }}
        >{loading ? "Signing in…" : "Sign In"}</button>
      </form>
    </div>
  );
}

// ── Auth Gate ─────────────────────────────────────────────────────────────────
function AuthGate() {
  const [authed, setAuthed] = React.useState(!!getAuthToken());

  React.useEffect(() => {
    if (!getAuthToken()) return;
    authFetch(`${NAFFCO_API}/api/alarms`).then(r => {
      if (r.status === 401) { clearAuthToken(); setAuthed(false); }
    }).catch(() => {});
  }, []);

  if (!authed) return <LoginScreen onLogin={() => setAuthed(true)} />;
  return <App onLogout={() => { clearAuthToken(); setAuthed(false); }} />;
}

const TABS = [
  { id: "overview", label: "Dashboard", icon: "Dashboard" },
  { id: "alarms", label: "Alarms", icon: "Flame" },
  { id: "calls", label: "Calls", icon: "Phone" },
  { id: "buildings", label: "Buildings", icon: "Building" },
];

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

  React.useEffect(() => {
    authFetch(`${NAFFCO_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 ─────────────────────────────────────────────────────
function BalanceIndicator() {
  const [bal, setBal] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    async function fetchBal() {
      try {
        const r = await authFetch(`${NAFFCO_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>
  );
}

// ── Dispatch Toggle ───────────────────────────────────────────────────────────
function DispatchToggle() {
  const [status, setStatus] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    async function poll() {
      try {
        const r = await authFetch(`${NAFFCO_API}/api/dispatch/status`);
        const d = await r.json();
        if (!cancelled) setStatus(d);
      } catch {}
    }
    poll();
    const id = setInterval(poll, 3000);
    return () => { cancelled = true; clearInterval(id); };
  }, []);

  const toggle = async () => {
    try {
      const r = await authFetch(`${NAFFCO_API}/api/dispatch/toggle`, { method: "POST" });
      const d = await r.json();
      setStatus(s => ({ ...s, paused: d.paused }));
    } catch {}
  };

  if (!status) return null;
  const paused = status.paused;

  return (
    <button
      onClick={toggle}
      className={`flex items-center gap-1.5 px-2.5 py-1 rounded-md text-[11px] font-medium transition-all border ${
        paused
          ? "bg-rose-500/10 border-rose-500/20 text-rose-300 hover:bg-rose-500/15"
          : "bg-emerald-500/10 border-emerald-500/20 text-emerald-300 hover:bg-emerald-500/15"
      }`}
      title={paused ? "Dispatch paused — click to resume" : "Dispatch active — click to pause"}
    >
      <span className={`w-1.5 h-1.5 rounded-full ${paused ? "bg-rose-400" : "bg-emerald-400 pulse-dot"}`}></span>
      {paused ? "Paused" : "Dispatching"}
      {!paused && status.alarmsPending > 0 && (
        <span className="text-[10px] font-mono bg-emerald-500/20 px-1 rounded">{status.alarmsPending}</span>
      )}
    </button>
  );
}

// ── Main App ──────────────────────────────────────────────────────────────────
function App({ onLogout }) {
  const [data, setData] = React.useState({ alarms: [], calls: [] });
  const [loading, setLoading] = React.useState(true);
  const [tab, setTab] = React.useState("overview");
  const [selectedAlarm, setSelectedAlarm] = React.useState(null);
  const [toasts, setToasts] = React.useState([]);
  const [now, setNow] = React.useState(new Date());
  const [refreshKey, setRefreshKey] = React.useState(0);

  const callManager = useCallManager();

  // Fetch data from API + auto refresh every 5s
  React.useEffect(() => {
    let cancelled = false;
    async function load() {
      try {
        const [aRes, cRes] = await Promise.all([
          authFetch(`${NAFFCO_API}/api/alarms`, { cache: "no-store" }),
          authFetch(`${NAFFCO_API}/api/calls`, { cache: "no-store" }),
        ]);
        if (!aRes.ok || !cRes.ok) throw new Error("API error");
        const [aData, cData] = await Promise.all([aRes.json(), cRes.json()]);
        if (cancelled) return;
        setData({ alarms: aData.alarms || [], calls: cData.calls || [] });
      } catch (err) {
        // silent
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    load();
    const id = setInterval(load, 5000);
    return () => { cancelled = true; clearInterval(id); };
  }, [refreshKey]);

  // Keep selectedAlarm in sync
  React.useEffect(() => {
    if (selectedAlarm) {
      const updated = (data.alarms || []).find(a => a.id === selectedAlarm.id);
      if (updated && JSON.stringify(updated) !== JSON.stringify(selectedAlarm)) {
        setSelectedAlarm(updated);
      }
    }
  }, [data]);

  // Clock tick
  React.useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 30000);
    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
  const handleCall = async (alarm) => {
    try {
      const r = await authFetch(`${NAFFCO_API}/api/dial`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          to: alarm.phoneNo,
          alarmId: alarm.alarmId,
          buildingName: alarm.buildingName,
          contactPerson: alarm.contactPerson,
          parameterType: alarm.parameterType,
          defaultLanguage: alarm.defaultLanguage,
        }),
      });
      if (!r.ok) throw new Error("HTTP " + r.status);
      pushToast({ tone: "success", title: `Call dispatched`, body: `Nova calling ${alarm.contactPerson} at ${alarm.phoneNo}` });
    } catch (err) {
      pushToast({ tone: "error", title: "Dial failed", body: err.message });
    }
    return true;
  };

  const handleDeleteCall = async (callId) => {
    try {
      const r = await authFetch(`${NAFFCO_API}/api/calls/${callId}`, { method: "DELETE" });
      if (!r.ok) throw new Error("HTTP " + r.status);
      setData(d => ({ ...d, calls: d.calls.filter(c => c.id !== callId) }));
      pushToast({ tone: "success", title: "Call deleted" });
    } catch (err) {
      pushToast({ tone: "error", title: "Delete failed", body: err.message });
    }
  };

  const handleDeleteAlarm = async (alarmId) => {
    try {
      const r = await authFetch(`${NAFFCO_API}/api/alarms/${alarmId}`, { method: "DELETE" });
      if (!r.ok) throw new Error("HTTP " + r.status);
      setData(d => ({ ...d, alarms: d.alarms.filter(a => a.id !== alarmId) }));
      setSelectedAlarm(null);
      pushToast({ tone: "success", title: "Alarm deleted" });
    } catch (err) {
      pushToast({ tone: "error", title: "Delete failed", body: err.message });
    }
  };

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

  return (
    <div className="h-screen flex bg-ink-950 text-ink-100 overflow-hidden">
      {/* 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-amber-500/15 text-amber-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">Naffco</span>
            <span className="text-[10px] text-ink-500 uppercase tracking-wider">Fire Alarm Monitoring</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">Operations</div>
          {TABS.map(t => {
            const Icn = I[t.icon];
            const active = tab === t.id;
            const count = ({
              alarms: data.alarms?.length,
              calls: data.calls?.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-amber-500/15 text-amber-200" : "bg-white/5 text-ink-400"
                  }`}>{count}</span>
                )}
              </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">Nova</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
                ? <>Operational · SSE connected{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} call{Object.values(callManager.calls).filter(c => c.status === "active").length > 1 ? "s" : ""}</span></>
                    : ""}</>
                : <>No backend connection</>}
            </div>
            <AgentPhone />
            <button
              onClick={onLogout}
              className="mt-2 pt-2 border-t border-white/5 w-full flex items-center gap-1.5 text-[11px] text-ink-500 hover:text-ink-300 transition-colors"
            >
              <I.ArrowRight size={10} /> Sign out
            </button>
          </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-amber-500/15 text-amber-300 inline-flex items-center justify-center">
              <I.Logo size={14} />
            </span>
            <span className="text-sm font-semibold">Naffco</span>
          </div>
          <div className="hidden md:block">
            <div className="text-[11px] text-ink-500 font-mono">
              {now.toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long", year: "numeric" })}
            </div>
          </div>
          <div className="flex-1"></div>
          <DispatchToggle />
          <BalanceIndicator />
          <div className="text-[11px] text-ink-400 font-mono hidden md:flex items-center gap-2">
            <I.Clock size={12} /> {fmtClock(now)} UTC+4
          </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="Refresh">
            <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-amber-500/20 text-amber-200 inline-flex items-center justify-center text-xs font-semibold">N</span>
            <div className="hidden lg:flex flex-col leading-tight">
              <span className="text-xs text-ink-200 font-medium">Naffco</span>
              <span className="text-[10px] text-ink-500">Fire Monitoring</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" /> Loading data…
              </span>
            </div>
          ) : tab === "overview" ? (
            <OverviewView data={data} onCall={handleCall} onSelectAlarm={setSelectedAlarm} onGoTab={goTab} />
          ) : tab === "alarms" ? (
            <AlarmsView data={data} onCall={handleCall} onSelectAlarm={setSelectedAlarm} onGoTab={goTab} />
          ) : tab === "calls" ? (
            <CallsView data={data} onSelectAlarm={setSelectedAlarm} onDelete={handleDeleteCall} />
          ) : tab === "buildings" ? (
            <BuildingsView data={data} />
          ) : null}
        </main>
      </div>

      {selectedAlarm && (
        <AlarmPanel
          alarm={selectedAlarm}
          data={data}
          onClose={() => setSelectedAlarm(null)}
          onCall={handleCall}
          onDelete={handleDeleteAlarm}
        />
      )}

      <ToastHost toasts={toasts} onDismiss={(id) => setToasts(arr => arr.filter(x => x.id !== id))} />

      <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(<AuthGate />);
