import { useState, type FormEvent, type ReactNode } from "react";
import { NavLink, useNavigate } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import {
  Braces,
  FileBox,
  FolderTree,
  History,
  LayoutDashboard,
  PackageOpen,
  PanelLeftClose,
  PanelLeftOpen,
  Search as SearchIcon,
  Server,
  ShieldCheck,
} from "lucide-react";
import { getHealth, listRuns } from "../api/service";
import { LATEST_RUN, useRunParam, useSetRunParam } from "../lib/run";
import { StatusPill } from "./StatusPill";

const NAV_ITEMS = [
  { path: "/", label: "Overview", icon: LayoutDashboard, end: true },
  { path: "/repositories", label: "Repositories", icon: Server, end: false },
  { path: "/publication-points", label: "Publication Points", icon: FolderTree, end: false },
  { path: "/objects", label: "Objects", icon: FileBox, end: false },
  { path: "/validation", label: "Validation", icon: ShieldCheck, end: false },
  { path: "/exports", label: "Exports", icon: PackageOpen, end: false },
  { path: "/runs", label: "Runs", icon: History, end: false },
  { path: "/api", label: "API", icon: Braces, end: false },
];

const COLLAPSE_KEY = "rpki-explorer.sidebar-collapsed";

function ConnectionPill() {
  const healthQuery = useQuery({
    queryKey: ["health"],
    queryFn: getHealth,
    refetchInterval: 60_000,
  });

  if (healthQuery.isPending) {
    return <StatusPill status="pending" label="connecting" />;
  }
  if (healthQuery.isError) {
    return <StatusPill status="error" label="API unreachable" />;
  }
  const health = healthQuery.data;
  return (
    <span title={health.latestReadyRun ? `Latest indexed run: ${health.latestReadyRun}` : undefined}>
      <StatusPill status="ok" label="connected" />
    </span>
  );
}

function RunSelector() {
  const runParam = useRunParam();
  const setRunParam = useSetRunParam();
  const runsQuery = useQuery({
    queryKey: ["runs", "selector"],
    queryFn: () => listRuns({ limit: 25 }),
    staleTime: 60_000,
    // Soak runs keep producing new runs; poll so the dropdown picks them up
    // without a manual page refresh.
    refetchInterval: 30_000,
  });
  const healthQuery = useQuery({ queryKey: ["health"], queryFn: getHealth });
  const latestId = healthQuery.data?.latestReadyRun ?? runsQuery.data?.items[0]?.runId;

  return (
    <div className="topbar-run">
      <label htmlFor="run-selector">Run</label>
      <select
        id="run-selector"
        value={runParam ?? ""}
        onChange={(event) => setRunParam(event.target.value || null)}
      >
        <option value="">{latestId ? `latest (${latestId})` : LATEST_RUN}</option>
        {(runsQuery.data?.items ?? []).map((run) => (
          <option key={run.runId} value={run.runId}>
            {run.runId}
          </option>
        ))}
      </select>
    </div>
  );
}

function TopbarSearch() {
  const navigate = useNavigate();
  const runParam = useRunParam();
  const [value, setValue] = useState("");

  const onSubmit = (event: FormEvent) => {
    event.preventDefault();
    const q = value.trim();
    if (!q) return;
    const params = new URLSearchParams({ q });
    if (runParam) params.set("run", runParam);
    navigate(`/search?${params.toString()}`);
  };

  return (
    <form className="topbar-search" role="search" onSubmit={onSubmit}>
      <span className="search-icon" aria-hidden="true">
        <SearchIcon size={14} />
      </span>
      <input
        type="search"
        value={value}
        onChange={(event) => setValue(event.target.value)}
        placeholder="Search URI, SHA-256, repository host…"
        aria-label="Global search"
      />
    </form>
  );
}

export function Shell({ children }: { children: ReactNode }) {
  const runParam = useRunParam();
  const [collapsed, setCollapsed] = useState(
    () => localStorage.getItem(COLLAPSE_KEY) === "1",
  );

  const toggleCollapsed = () => {
    setCollapsed((prev) => {
      localStorage.setItem(COLLAPSE_KEY, prev ? "0" : "1");
      return !prev;
    });
  };

  const search = runParam ? `?run=${encodeURIComponent(runParam)}` : "";

  return (
    <div className={`shell${collapsed ? " collapsed" : ""}`}>
      <a href="#main-content" className="skip-link">
        Skip to content
      </a>
      <div className="shell-brand">
        <span className="brand-badge" aria-hidden="true">
          <ShieldCheck size={15} />
        </span>
        <span className="brand-name">RPKI Explorer</span>
      </div>

      <div className="shell-topbar">
        <TopbarSearch />
        <RunSelector />
        <ConnectionPill />
      </div>

      <nav className="shell-nav" aria-label="Primary">
        <button
          type="button"
          className="nav-toggle"
          onClick={toggleCollapsed}
          aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
        >
          {collapsed ? (
            <PanelLeftOpen size={15} aria-hidden="true" />
          ) : (
            <PanelLeftClose size={15} aria-hidden="true" />
          )}
          {!collapsed && <span>Collapse</span>}
        </button>
        {NAV_ITEMS.map((item) => (
          <NavLink
            key={item.path}
            to={{ pathname: item.path, search }}
            end={item.end}
            className={({ isActive }) => (isActive ? "active" : undefined)}
          >
            <item.icon size={15} aria-hidden="true" />
            <span className="nav-label">{item.label}</span>
          </NavLink>
        ))}
        <div className="nav-footer">ours RP query layer</div>
      </nav>

      <main className="shell-main" id="main-content" tabIndex={-1}>
        {children}
      </main>
    </div>
  );
}
