import React, { useEffect, useMemo, useState } from "react";
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  Tooltip,
  Legend,
  ResponsiveContainer,
  CartesianGrid,
} from "recharts";

const VIZ = {
  STATS: "stats",
  COMPUTERS: "computers",
  COMPUTER_DETAILS: "computer_details",
  NET_GRAPH: "net_graph",
};

function fmtTs(ts) {
  if (!ts) return "";
  return String(ts).replace("T", " ").replace("Z", "");
}

async function fetchJson(url, { method = "GET", headers = {}, body } = {}) {
  const res = await fetch(url, {
    method,
    credentials: "include",
    headers: {
      "Content-Type": "application/json",
      ...headers,
    },
    body: body ? JSON.stringify(body) : undefined,
  });

  const text = await res.text();
  let data;
  try {
    data = text ? JSON.parse(text) : null;
  } catch {
    data = { raw: text };
  }
  if (!res.ok) {
    const msg = data?.error || data?.message || res.statusText;
    throw new Error(msg);
  }
  return data;
}

/** ✅ Use existing theme.css look: panel / btn / select / input / pill */
function Panel({ title, right, children, subtitle }) {
  return (
    <div className="panel" style={{ marginBottom: 14 }}>
      <div className="panel-head">
        <div>
          <div className="panel-title">{title}</div>
          {subtitle ? (
            <div style={{ color: "var(--dim)", fontSize: 12, marginTop: 4 }}>{subtitle}</div>
          ) : null}
        </div>
        {right}
      </div>
      <div className="panel-body">{children}</div>
    </div>
  );
}

function Select({ label, value, onChange, options, disabled }) {
  return (
    <label style={{ display: "grid", gap: 6 }}>
      <div style={{ fontSize: 12, color: "var(--dim)" }}>{label}</div>
      <select
        className="select"
        value={value}
        disabled={disabled}
        onChange={(e) => onChange(e.target.value)}
      >
        {options.map((o) => (
          <option key={o.value} value={o.value}>
            {o.label}
          </option>
        ))}
      </select>
    </label>
  );
}

function Pill({ children }) {
  return <span className="pill">{children}</span>;
}

function Table({ columns, rows, emptyText = "Нема податоци." }) {
  return (
    <div style={{ overflow: "auto" }}>
      <table className="table">
        <thead>
          <tr>
            {columns.map((c) => (
              <th key={c.key}>{c.title}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.length === 0 ? (
            <tr>
              <td colSpan={columns.length} style={{ color: "var(--dim)", padding: 12 }}>
                {emptyText}
              </td>
            </tr>
          ) : (
            rows.map((r, idx) => (
              <tr key={idx}>
                {columns.map((c) => (
                  <td key={c.key}>{c.render ? c.render(r) : String(r[c.key] ?? "")}</td>
                ))}
              </tr>
            ))
          )}
        </tbody>
      </table>
    </div>
  );
}

export default function NetIntelViz({ baseUrl = "" }) {
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState("");

  const [me, setMe] = useState(null);
  const [envs, setEnvs] = useState(["default"]);
  const [env, setEnv] = useState("default");

  const [viz, setViz] = useState(VIZ.NET_GRAPH);

  const [stats, setStats] = useState(null);
  const [computers, setComputers] = useState([]);
  const [computerName, setComputerName] = useState("");
  const [computerDetails, setComputerDetails] = useState(null);

  const [sinceHours, setSinceHours] = useState("24");
  const [graph, setGraph] = useState(null);

  const api = useMemo(() => (baseUrl || "").replace(/\/+$/, ""), [baseUrl]);

  const envOptions = useMemo(() => {
    const uniq = [...new Set(envs)];
    return uniq.map((e) => ({ value: e, label: e }));
  }, [envs]);

  const computerOptions = useMemo(() => {
    const opts = computers.map((c) => ({ value: c.name, label: c.name }));
    return [{ value: "", label: "all" }, ...opts];
  }, [computers]);

  const vizOptions = [
    { value: VIZ.STATS, label: "Stats (24h)" },
    { value: VIZ.COMPUTERS, label: "Computers" },
    { value: VIZ.COMPUTER_DETAILS, label: "Computer details" },
    { value: VIZ.NET_GRAPH, label: "Network graph" },
  ];

  async function loadMe() {
    const data = await fetchJson(`${api}/api/me`);
    setMe(data?.user || null);
  }

  async function loadEnvs() {
    try {
      const data = await fetchJson(`${api}/api/admin/environments`);
      const list = data?.environments?.length ? data.environments : ["default"];
      setEnvs(list);
      if (!list.includes(env)) setEnv(list[0] || "default");
    } catch {
      setEnvs(["default"]);
      setEnv("default");
    }
  }

  async function loadStats(selectedEnv) {
    const data = await fetchJson(`${api}/api/stats`, {
      headers: { "X-Env": selectedEnv || env || "default" },
    });
    setStats(data);
  }

  async function loadComputers(selectedEnv) {
    const data = await fetchJson(`${api}/api/computers`, {
      headers: { "X-Env": selectedEnv || env || "default" },
    });
    setComputers(Array.isArray(data) ? data : []);
  }

  async function loadComputerDetails(name) {
    if (!name) {
      setComputerDetails(null);
      return;
    }
    const data = await fetchJson(`${api}/api/computer/${encodeURIComponent(name)}`, {
      headers: { "X-Env": env || "default" },
    });
    setComputerDetails(data);
  }

  async function loadNetGraph() {
    const qs = new URLSearchParams();
    qs.set("env", env || "default");
    qs.set("since_hours", String(parseInt(sinceHours || "24", 10) || 24));
    if (computerName) qs.set("computer", computerName);

    const data = await fetchJson(`${api}/api/graph/net?${qs.toString()}`, {
      headers: { "X-Env": env || "default" },
    });
    setGraph(data);
  }
  function MiniBipartiteGraph({ nodes = [], edges = [] }) {
  const comps = nodes.filter((n) => (n.subTitle || "").toLowerCase().includes("computer"));
  const ips = nodes.filter((n) => (n.subTitle || "").toLowerCase().includes("remote"));

  const width = 1100;
  const height = 520;
  const pad = 40;

  const compPos = comps.map((n, i) => ({
    ...n,
    x: pad,
    y: pad + (i * (height - 2 * pad)) / Math.max(1, comps.length - 1),
  }));

  const ipPos = ips.map((n, i) => ({
    ...n,
    x: width - pad,
    y: pad + (i * (height - 2 * pad)) / Math.max(1, ips.length - 1),
  }));

  const pos = new Map();
  [...compPos, ...ipPos].forEach((n) => pos.set(n.id, n));

  const shownEdges = edges.slice(0, 120);

  return (
    <div style={{ overflow: "auto" }}>
      <svg width={width} height={height} style={{ borderRadius: 16, background: "rgba(255,255,255,0.03)" }}>
        {shownEdges.map((e, idx) => {
          const s = pos.get(e.source);
          const t = pos.get(e.target);
          if (!s || !t) return null;
          const v = Number(e.mainStat || 1);
          const strokeWidth = Math.max(1, Math.min(6, Math.log2(v + 1)));
          return (
            <line
              key={idx}
              x1={s.x}
              y1={s.y}
              x2={t.x}
              y2={t.y}
              stroke="rgba(120,180,255,0.25)"
              strokeWidth={strokeWidth}
            />
          );
        })}

        {compPos.map((n) => (
          <g key={n.id}>
            <circle cx={n.x} cy={n.y} r={6} fill="rgba(255,255,255,0.9)" />
            <text x={n.x + 12} y={n.y + 4} fontSize="11" fill="rgba(255,255,255,0.85)">
              {n.title}
            </text>
          </g>
        ))}

        {ipPos.map((n) => (
          <g key={n.id}>
            <circle cx={n.x} cy={n.y} r={6} fill="rgba(80,160,255,0.95)" />
            <text x={n.x - 12} y={n.y + 4} textAnchor="end" fontSize="11" fill="rgba(255,255,255,0.85)">
              {n.title}
            </text>
          </g>
        ))}
      </svg>

      <div style={{ color: "var(--dim)", fontSize: 12, marginTop: 10 }}>
        Tip: ако има премногу линии, намали Hours или избери конкретен Computer.
      </div>
    </div>
  );
}


  async function refreshAll(nextViz = viz, nextEnv = env) {
    setErr("");
    setLoading(true);
    try {
      if (nextViz === VIZ.STATS) {
        await loadStats(nextEnv);
      } else if (nextViz === VIZ.COMPUTERS) {
        await loadComputers(nextEnv);
      } else if (nextViz === VIZ.COMPUTER_DETAILS) {
        await loadComputers(nextEnv);
        if (computerName) await loadComputerDetails(computerName);
      } else if (nextViz === VIZ.NET_GRAPH) {
        await loadComputers(nextEnv);
        await loadNetGraph();
      }
    } catch (e) {
      setErr(e.message || "Грешка при вчитување.");
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    (async () => {
      setLoading(true);
      setErr("");
      try {
        await loadMe();
        await loadEnvs();
        await refreshAll(VIZ.NET_GRAPH, env);
      } catch (e) {
        setErr(e.message || "Неуспешно поврзување.");
      } finally {
        setLoading(false);
      }
    })();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [api]);

  const historySeries = useMemo(() => {
    const hist = computerDetails?.history || [];
    const rows = [...hist].reverse().slice(-80);
    return rows.map((r) => ({
      t: fmtTs(r.timestamp),
      cpu: Number(r.cpu_usage ?? 0),
      ram: Number(r.ram_usage ?? 0),
      disk: Number(r.disk_usage ?? 0),
      sent: Number(r.network_sent_mb ?? 0),
      recv: Number(r.network_recv_mb ?? 0),
    }));
  }, [computerDetails]);

  const nodes = graph?.nodes || [];
  const edges = graph?.edges || [];
  const meta = graph?.meta || {};

  return (
    <div>
      {/* HEADER / CONTROLS */}
      <Panel
        title="Visualizations"
        subtitle={me ? `Logged: ${me.email} • tenant: ${me.tenant_id} • role: ${me.role}` : "Not logged"}
        right={
          <div style={{ display: "flex", gap: 10, alignItems: "end", flexWrap: "wrap" }}>
            <Select
              label="Env"
              value={env}
              disabled={loading}
              onChange={(v) => {
                setEnv(v);
                refreshAll(viz, v);
              }}
              options={envOptions}
            />

            <Select
              label="View"
              value={viz}
              disabled={loading}
              onChange={(v) => {
                setViz(v);
                refreshAll(v, env);
              }}
              options={vizOptions}
            />

            {(viz === VIZ.COMPUTER_DETAILS || viz === VIZ.NET_GRAPH) && (
              <Select
                label="Computer"
                value={computerName}
                disabled={loading}
                onChange={(v) => {
                  setComputerName(v);
                  if (viz === VIZ.COMPUTER_DETAILS) loadComputerDetails(v).catch((e) => setErr(e.message));
                  if (viz === VIZ.NET_GRAPH) loadNetGraph().catch((e) => setErr(e.message));
                }}
                options={computerOptions}
              />
            )}

            {viz === VIZ.NET_GRAPH && (
              <Select
                label="Hours"
                value={sinceHours}
                disabled={loading}
                onChange={(v) => setSinceHours(v)}
                options={[
                  { value: "1", label: "1" },
                  { value: "6", label: "6" },
                  { value: "12", label: "12" },
                  { value: "24", label: "24" },
                  { value: "48", label: "48" },
                  { value: "72", label: "72" },
                ]}
              />
            )}

            <button className="btn primary" disabled={loading} onClick={() => refreshAll(viz, env)}>
              {loading ? "Loading…" : "Refresh"}
            </button>
          </div>
        }
      >
        {err ? (
          <div style={{ color: "#ffb4b4", background: "rgba(255,0,0,0.08)", padding: 10, borderRadius: 12 }}>
            {err}
          </div>
        ) : (
          <div style={{ color: "var(--dim)", fontSize: 12 }}>
            Избери “View” за да смениш што се прикажува.
          </div>
        )}
      </Panel>
      <Panel title="Graph (SVG)" subtitle="Computers left, IPs right, lines = connections">
  <MiniBipartiteGraph nodes={nodes} edges={edges} />
</Panel>


      {/* STATS */}
      {viz === VIZ.STATS && (
        <Panel title="Stats (24h)" subtitle="From /api/stats">
          <div className="stats-grid" style={{ marginTop: 0 }}>
            <div className="stat-card">
              <div className="label">Sysmon Events</div>
              <div className="value">{stats?.total_sysmon_events ?? "—"}</div>
              <div className="sub">Last 24 hours</div>
            </div>
            <div className="stat-card">
              <div className="label">Network Connections</div>
              <div className="value">{stats?.total_network_connections ?? "—"}</div>
              <div className="sub">Last 24 hours</div>
            </div>
            <div className="stat-card">
              <div className="label">Server Time</div>
              <div className="value" style={{ fontSize: 18 }}>
                {fmtTs(stats?.server_time) || "—"}
              </div>
              <div className="sub">Now</div>
            </div>
          </div>
        </Panel>
      )}

      {/* COMPUTERS */}
      {viz === VIZ.COMPUTERS && (
        <Panel title="Computers" subtitle="From /api/computers">
          <Table
            columns={[
              { key: "name", title: "Name" },
              { key: "user", title: "User" },
              { key: "ip", title: "IP" },
              { key: "os", title: "OS" },
              { key: "status", title: "Status" },
              { key: "avg_cpu", title: "Avg CPU" },
              { key: "avg_ram", title: "Avg RAM" },
              { key: "recent_logs", title: "Logs(24h)" },
              { key: "recent_sysmon", title: "Sysmon(24h)" },
              { key: "last_seen", title: "Last seen", render: (r) => fmtTs(r.last_seen) },
            ]}
            rows={computers}
            emptyText="No computers for this env."
          />
        </Panel>
      )}

      {/* COMPUTER DETAILS */}
      {viz === VIZ.COMPUTER_DETAILS && (
        <>
          <Panel
            title="Computer details"
            subtitle="From /api/computer/<name>"
            right={
              <button
                className="btn"
                disabled={loading || !computerName}
                onClick={() => loadComputerDetails(computerName).catch((e) => setErr(e.message))}
              >
                Reload
              </button>
            }
          >
            {!computerName ? (
              <div style={{ color: "var(--dim)" }}>Select a computer.</div>
            ) : !computerDetails ? (
              <div style={{ color: "var(--dim)" }}>Loading…</div>
            ) : (
              <div className="stats-grid" style={{ marginTop: 0 }}>
                <div className="stat-card">
                  <div className="label">Name</div>
                  <div className="value">{computerDetails.computer?.name}</div>
                  <div className="sub">{computerDetails.computer?.ip} • {computerDetails.computer?.os}</div>
                </div>
                <div className="stat-card">
                  <div className="label">User</div>
                  <div className="value">{computerDetails.computer?.user || "—"}</div>
                  <div className="sub">
                    {fmtTs(computerDetails.computer?.first_seen)} → {fmtTs(computerDetails.computer?.last_seen)}
                  </div>
                </div>
                <div className="stat-card">
                  <div className="label">Total logs</div>
                  <div className="value">{computerDetails.computer?.total_logs ?? "—"}</div>
                  <div className="sub">Env: {computerDetails.computer?.env_name || env}</div>
                </div>
              </div>
            )}
          </Panel>

          <Panel title="Performance charts" subtitle="Last ~80 history rows">
            {historySeries.length === 0 ? (
              <div style={{ color: "var(--dim)" }}>No history data.</div>
            ) : (
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
                <div style={{ height: 280 }}>
                  <div style={{ marginBottom: 8, color: "var(--dim)", fontSize: 12 }}>CPU / RAM / Disk</div>
                  <ResponsiveContainer width="100%" height="100%">
                    <LineChart data={historySeries}>
                      <CartesianGrid strokeDasharray="3 3" />
                      <XAxis dataKey="t" hide />
                      <YAxis />
                      <Tooltip />
                      <Legend />
                      <Line type="monotone" dataKey="cpu" dot={false} />
                      <Line type="monotone" dataKey="ram" dot={false} />
                      <Line type="monotone" dataKey="disk" dot={false} />
                    </LineChart>
                  </ResponsiveContainer>
                </div>

                <div style={{ height: 280 }}>
                  <div style={{ marginBottom: 8, color: "var(--dim)", fontSize: 12 }}>Network MB sent/recv</div>
                  <ResponsiveContainer width="100%" height="100%">
                    <LineChart data={historySeries}>
                      <CartesianGrid strokeDasharray="3 3" />
                      <XAxis dataKey="t" hide />
                      <YAxis />
                      <Tooltip />
                      <Legend />
                      <Line type="monotone" dataKey="sent" dot={false} />
                      <Line type="monotone" dataKey="recv" dot={false} />
                    </LineChart>
                  </ResponsiveContainer>
                </div>
              </div>
            )}
          </Panel>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
            <Panel title="Processes (current)" subtitle="computer_processes_current (limit 200)">
              <Table
                columns={[
                  { key: "pid", title: "PID" },
                  { key: "name", title: "Name" },
                  { key: "username", title: "User" },
                  { key: "cpu_percent", title: "CPU%" },
                  { key: "memory_mb", title: "MemMB" },
                  { key: "timestamp", title: "Time", render: (r) => fmtTs(r.timestamp) },
                ]}
                rows={computerDetails?.recent_processes || []}
              />
            </Panel>

            <Panel title="Sysmon events" subtitle="sysmon_events (limit 200)">
              <Table
                columns={[
                  { key: "event_id", title: "Event" },
                  { key: "event_type", title: "Type" },
                  {
                    key: "message",
                    title: "Message",
                    render: (r) =>
                      (r.message || "").slice(0, 70) + ((r.message || "").length > 70 ? "…" : ""),
                  },
                  { key: "timestamp", title: "Time", render: (r) => fmtTs(r.timestamp) },
                ]}
                rows={computerDetails?.sysmon_events || []}
              />
            </Panel>
          </div>

          <Panel title="Network connections" subtitle="network_connections (limit 100)">
            <Table
              columns={[
                { key: "pid", title: "PID" },
                { key: "process_name", title: "Process" },
                { key: "local_address", title: "Local" },
                { key: "remote_address", title: "Remote" },
                { key: "status", title: "Status" },
                { key: "timestamp", title: "Time", render: (r) => fmtTs(r.timestamp) },
              ]}
              rows={computerDetails?.network_connections || []}
            />
          </Panel>
        </>
      )}

      {/* NET GRAPH */}
      {viz === VIZ.NET_GRAPH && (
        <>
          <Panel
            title="Network graph (computer → remote IP)"
            subtitle="From /api/graph/net"
            right={
              <button className="btn" disabled={loading} onClick={() => loadNetGraph().catch((e) => setErr(e.message))}>
                Reload graph
              </button>
            }
          >
            <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
              <Pill>env: {meta?.env || env}</Pill>
              <Pill>hours: {meta?.since_hours ?? sinceHours}</Pill>
              <Pill>computer: {meta?.computer || "all"}</Pill>
              <Pill>nodes: {nodes.length}</Pill>
              <Pill>edges: {edges.length}</Pill>
            </div>
          </Panel>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
            <Panel title="Top edges" subtitle="Each row = number of connections">
              <Table
                columns={[
                  { key: "source", title: "Source" },
                  { key: "target", title: "Target" },
                  { key: "mainStat", title: "Count" },
                ]}
                rows={edges.slice(0, 80)}
                emptyText="No edges (maybe no traffic in that period)."
              />
            </Panel>

            <Panel title="Nodes" subtitle="Computers + remote IP">
              <Table
                columns={[
                  { key: "title", title: "Title" },
                  { key: "subTitle", title: "Type" },
                ]}
                rows={nodes.slice(0, 120)}
              />
            </Panel>
          </div>
        </>
      )}
    </div>
  );
}
