import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import {
  Bell,
  Check,
  LogOut,
  PanelRight,
  Settings,
  SlidersHorizontal,
  SquareArrowOutUpRight,
  User,
} from "lucide-react";
import type { SplitMode, TabType, ToolsTab } from "@/types/ui-types";
import { getAlertFirings } from "@/api/alerts-api";
import { isElectron } from "@/lib/electron";
import { readRailPreference, setRailPreference } from "./rail-preferences";
import { visibleRailItems } from "./rail-items";
import { useAiAvailability } from "@/hooks/use-ai-availability";

export type RailView =
  | "hosts"
  | "credentials"
  | "termix-id"
  | "quick-connect"
  | "serial"
  | ToolsTab
  | "connections"
  | "session-logs"
  | "user-profile"
  | "admin-settings"
  | "alerts"
  | "automations"
  | "ai"
  | "fleets"
  | "workspaces";

export type HideableRailView =
  | Exclude<RailView, "user-profile" | "admin-settings">
  | "network_graph"
  | "homepage";

type RailItem =
  | {
      kind?: undefined;
      view: RailView;
      icon: React.ReactNode;
      title: string;
      dot?: boolean;
      promotable?: boolean;
      rightDockable?: boolean;
    }
  | { kind: "tab"; tabType: TabType; icon: React.ReactNode; title: string }
  | { kind: "separator" };

function buildRailButtons(
  splitMode: SplitMode,
  t: (key: string) => string,
  hidden: Set<string>,
): RailItem[] {
  const all: RailItem[] = [];
  for (const item of visibleRailItems()) {
    const Icon = item.icon;
    if (item.kind === "tab") {
      all.push({
        kind: "tab",
        tabType: item.id as TabType,
        icon: <Icon size={16} />,
        title: t(item.labelKey),
      });
    } else {
      all.push({
        view: item.id as RailView,
        icon: <Icon size={16} />,
        title: t(item.labelKey),
        dot: item.id === "split-screen" ? splitMode !== "none" : undefined,
        promotable: item.promotable,
        rightDockable: item.rightDockable,
      });
    }
    if (item.separatorAfter) all.push({ kind: "separator" });
  }

  // Filter out hidden items, then collapse consecutive/leading/trailing separators
  const filtered = all.filter((item) => {
    if (item.kind === "separator") return true;
    if ("tabType" in item) return !hidden.has(item.tabType);
    return !hidden.has(item.view);
  });

  const result: RailItem[] = [];
  for (const item of filtered) {
    if (item.kind === "separator") {
      if (result.length === 0 || result[result.length - 1].kind === "separator")
        continue;
      result.push(item);
    } else {
      result.push(item);
    }
  }
  if (result[result.length - 1]?.kind === "separator") result.pop();
  return result;
}

const btnBase =
  "relative flex items-center h-7 rounded shrink-0 transition-colors gap-2.5";
const btnStyle = { margin: "0 4px", padding: "0 8px" };

export function AppRail({
  railView,
  sidebarOpen,
  splitMode,
  username,
  isAdmin,
  onRailClick,
  onOpenTab,
  onOpenInRightDock,
  onLogout,
}: {
  railView: RailView;
  sidebarOpen: boolean;
  splitMode: SplitMode;
  username: string;
  isAdmin: boolean;
  onRailClick: (view: RailView) => void;
  onOpenTab?: (type: TabType) => void;
  onOpenInRightDock?: (view: RailView) => void;
  onLogout: () => void;
}) {
  const { t } = useTranslation();
  const [hovered, setHovered] = useState(false);
  const [pinned, setPinned] = useState(() => readRailPreference("pinAppRail"));
  const [expandOnHover, setExpandOnHover] = useState(() =>
    readRailPreference("expandAppRailOnHover"),
  );
  const [menuPos, setMenuPos] = useState<{ x: number; y: number } | null>(null);
  // Which promotable item was right-clicked, so the menu can offer to open it
  // as a tab. Null when the right-click landed on empty rail space.
  const [menuTarget, setMenuTarget] = useState<{
    view: RailView;
    title: string;
    promotable?: boolean;
    rightDockable?: boolean;
  } | null>(null);
  const [unreadAlerts, setUnreadAlerts] = useState(0);

  useEffect(() => {
    let cancelled = false;
    let intervalId: ReturnType<typeof setInterval> | null = null;

    const poll = () => {
      if (document.visibilityState === "hidden") return;
      getAlertFirings({ acknowledged: false, limit: 50 })
        .then((firings) => {
          if (!cancelled) setUnreadAlerts(firings.length);
        })
        .catch(() => {});
    };

    const start = () => {
      if (intervalId !== null) return;
      intervalId = setInterval(poll, 30000);
    };
    const stop = () => {
      if (intervalId === null) return;
      clearInterval(intervalId);
      intervalId = null;
    };
    const onVisibility = () => {
      if (document.visibilityState === "hidden") {
        stop();
        return;
      }
      poll();
      start();
    };

    poll();
    if (document.visibilityState !== "hidden") start();
    document.addEventListener("visibilitychange", onVisibility);

    return () => {
      cancelled = true;
      stop();
      document.removeEventListener("visibilitychange", onVisibility);
    };
  }, []);
  const [hiddenTabs, setHiddenTabs] = useState<Set<string>>(() => {
    try {
      const stored = localStorage.getItem("hiddenRailTabs");
      return stored ? new Set(JSON.parse(stored)) : new Set();
    } catch {
      return new Set();
    }
  });

  useEffect(() => {
    const pinHandler = () => setPinned(readRailPreference("pinAppRail"));
    const hoverHandler = () =>
      setExpandOnHover(readRailPreference("expandAppRailOnHover"));
    window.addEventListener("pinAppRailChanged", pinHandler);
    window.addEventListener("expandAppRailOnHoverChanged", hoverHandler);
    return () => {
      window.removeEventListener("pinAppRailChanged", pinHandler);
      window.removeEventListener("expandAppRailOnHoverChanged", hoverHandler);
    };
  }, []);

  useEffect(() => {
    if (!menuPos) return;
    const onDown = (e: MouseEvent) => {
      if (!(e.target as HTMLElement).closest("[data-rail-context-menu]")) {
        setMenuPos(null);
      }
    };
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") setMenuPos(null);
    };
    window.addEventListener("mousedown", onDown);
    window.addEventListener("keydown", onKey);
    return () => {
      window.removeEventListener("mousedown", onDown);
      window.removeEventListener("keydown", onKey);
    };
  }, [menuPos]);

  const { userEnabled: aiEnabled } = useAiAvailability();

  useEffect(() => {
    const handler = () => {
      try {
        const stored = localStorage.getItem("hiddenRailTabs");
        setHiddenTabs(stored ? new Set(JSON.parse(stored)) : new Set());
      } catch {
        setHiddenTabs(new Set());
      }
    };
    window.addEventListener("hiddenRailTabsChanged", handler);
    return () => window.removeEventListener("hiddenRailTabsChanged", handler);
  }, []);

  // Termix ID publishes SSH public keys under a claimed public handle for
  // other servers to fetch -- meaningless for a standalone desktop install
  // with no synced multi-device account, so it stays hidden until a remote
  // server is actually connected.
  const [isRemoteSyncConnected, setIsRemoteSyncConnected] = useState(
    () => !isElectron(),
  );

  useEffect(() => {
    if (!isElectron()) return;
    let cancelled = false;
    const refreshSyncStatus = () => {
      window.electronAPI
        ?.invoke?.("get-remote-sync-config")
        .then((config) => {
          if (!cancelled) {
            setIsRemoteSyncConnected(
              !!(config as { serverUrl?: string } | null)?.serverUrl,
            );
          }
        })
        .catch(() => {});
    };
    refreshSyncStatus();
    const unsubscribe = window.electronAPI?.onRemoteSyncStatusChanged?.(() =>
      refreshSyncStatus(),
    );
    return () => {
      cancelled = true;
      unsubscribe?.();
    };
  }, []);

  const railExpanded = pinned || (expandOnHover && hovered);
  const effectiveHiddenTabs = new Set([
    ...hiddenTabs,
    ...(isRemoteSyncConnected ? [] : ["termix-id"]),
    // The assistant is hidden until an admin has enabled it instance-wide and
    // the user has said yes, so someone who declined never sees the entry.
    ...(aiEnabled ? [] : ["ai"]),
  ]);
  const railButtons = buildRailButtons(splitMode, t, effectiveHiddenTabs);

  const togglePinned = () => {
    setRailPreference("pinAppRail", !pinned);
    setMenuPos(null);
  };

  const toggleExpandOnHover = () => {
    setRailPreference("expandAppRailOnHover", !expandOnHover);
    setMenuPos(null);
  };

  return (
    <div
      className="hidden md:flex flex-col items-stretch bg-sidebar border-r border-border shrink-0 overflow-hidden pt-2 gap-1 transition-[width] duration-200 min-h-0"
      style={{ width: railExpanded ? 160 : 40 }}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      onContextMenu={(e) => {
        e.preventDefault();
        // Keep the menu on screen when right-clicking near the viewport edges
        const MENU_W = 190;
        const MENU_H = 96;
        setMenuPos({
          x: Math.min(e.clientX, window.innerWidth - MENU_W - 8),
          y: Math.min(e.clientY, window.innerHeight - MENU_H - 8),
        });
        if (!(e.target as HTMLElement).closest("[data-rail-promotable]")) {
          setMenuTarget(null);
        }
      }}
    >
      <div className="flex flex-col flex-1 gap-1 overflow-y-auto scrollbar-none min-h-0">
        {railButtons.map((item, i) =>
          item.kind === "separator" ? (
            <div
              key={`sep-${i}`}
              className="mx-auto h-px bg-border my-0.5 shrink-0 transition-[width] duration-200"
              style={{ width: railExpanded ? "calc(100% - 16px)" : 20 }}
            />
          ) : "tabType" in item ? (
            <button
              key={item.tabType}
              onClick={() => onOpenTab?.(item.tabType)}
              style={btnStyle}
              className={`${btnBase} text-muted-foreground hover:text-foreground hover:bg-muted/60`}
            >
              <span
                className="shrink-0 flex items-center justify-center"
                style={{ width: 16, height: 16 }}
              >
                {item.icon}
              </span>
              <span
                className={`text-xs font-medium whitespace-nowrap overflow-hidden transition-[opacity,width] duration-150 ${
                  railExpanded ? "opacity-100 delay-75" : "opacity-0 w-0"
                }`}
              >
                {item.title}
              </span>
            </button>
          ) : (
            <button
              key={item.view}
              onClick={(e) => {
                if (item.promotable && (e.ctrlKey || e.metaKey)) {
                  onOpenTab?.(item.view as TabType);
                  return;
                }
                onRailClick(item.view);
              }}
              onAuxClick={(e) => {
                if (e.button !== 1 || !item.promotable) return;
                e.preventDefault();
                onOpenTab?.(item.view as TabType);
              }}
              onContextMenu={() => {
                if (item.promotable || item.rightDockable)
                  setMenuTarget({
                    view: item.view,
                    title: item.title,
                    promotable: item.promotable,
                    rightDockable: item.rightDockable,
                  });
              }}
              data-rail-promotable={
                item.promotable || item.rightDockable ? "" : undefined
              }
              title={
                item.promotable
                  ? `${item.title}\n${t("nav.openAsTabHint")}`
                  : item.title
              }
              style={btnStyle}
              className={`${btnBase} ${
                sidebarOpen && railView === item.view
                  ? "text-accent-brand bg-accent-brand/10"
                  : "text-muted-foreground hover:text-foreground hover:bg-muted/60"
              }`}
            >
              <span
                className="shrink-0 flex items-center justify-center"
                style={{ width: 16, height: 16 }}
              >
                {item.icon}
              </span>
              <span
                className={`text-xs font-medium whitespace-nowrap overflow-hidden transition-[opacity,width] duration-150 ${
                  railExpanded ? "opacity-100 delay-75" : "opacity-0 w-0"
                }`}
              >
                {item.title}
              </span>
              {item.dot && (
                <span className="absolute top-0.5 right-0.5 size-1.5 rounded-full bg-accent-brand" />
              )}
            </button>
          ),
        )}
      </div>

      <div className="shrink-0 flex flex-col gap-1 border-t border-border pt-1 pb-1">
        {[
          {
            view: "alerts" as RailView,
            icon: <Bell size={16} />,
            title: t("nav.alerts"),
            promotable: true,
          },
          {
            view: "user-profile" as RailView,
            icon: <User size={16} />,
            title: t("nav.userProfile"),
          },
          ...(isAdmin
            ? [
                {
                  view: "admin-settings" as RailView,
                  icon: <Settings size={16} />,
                  title: t("nav.admin"),
                },
              ]
            : []),
        ].map((item) => (
          <button
            key={item.view}
            onClick={(e) => {
              if (item.promotable && (e.ctrlKey || e.metaKey)) {
                onOpenTab?.(item.view as TabType);
                return;
              }
              onRailClick(item.view);
            }}
            onAuxClick={(e) => {
              if (e.button !== 1 || !item.promotable) return;
              e.preventDefault();
              onOpenTab?.(item.view as TabType);
            }}
            onContextMenu={() => {
              if (item.promotable)
                setMenuTarget({
                  view: item.view,
                  title: item.title,
                  promotable: item.promotable,
                  rightDockable: true,
                });
            }}
            data-rail-promotable={item.promotable ? "" : undefined}
            title={
              item.promotable
                ? `${item.title}\n${t("nav.openAsTabHint")}`
                : item.title
            }
            style={btnStyle}
            className={`${btnBase} ${
              sidebarOpen && railView === item.view
                ? "text-accent-brand bg-accent-brand/10"
                : "text-muted-foreground hover:text-foreground hover:bg-muted/60"
            }`}
          >
            <span
              className="relative shrink-0 flex items-center justify-center"
              style={{ width: 16, height: 16 }}
            >
              {item.icon}
              {item.view === "alerts" && unreadAlerts > 0 && (
                <span className="absolute -top-1 -right-1 flex size-3 items-center justify-center rounded-full bg-destructive text-[8px] font-bold text-white leading-none">
                  {unreadAlerts > 9 ? "9+" : unreadAlerts}
                </span>
              )}
            </span>
            <span
              className={`text-xs font-medium whitespace-nowrap overflow-hidden transition-[opacity,width] duration-150 ${railExpanded ? "opacity-100 delay-75" : "opacity-0 w-0"}`}
            >
              {item.title}
            </span>
          </button>
        ))}
        <div className="mx-2 my-1 border-t border-border" />
        <button
          onClick={onLogout}
          style={btnStyle}
          className={`${btnBase} text-muted-foreground hover:text-destructive hover:bg-destructive/10`}
        >
          <span
            className="shrink-0 flex items-center justify-center"
            style={{ width: 16, height: 16 }}
          >
            <LogOut size={16} />
          </span>
          <span
            className={`text-xs font-medium whitespace-nowrap overflow-hidden transition-[opacity,width] duration-150 ${railExpanded ? "opacity-100 delay-75" : "opacity-0 w-0"}`}
          >
            {t("common.logout")}
          </span>
        </button>
      </div>

      <div className="shrink-0 border-t border-border">
        <button
          className="flex items-center gap-2.5 w-full h-10 text-muted-foreground hover:text-foreground hover:bg-muted/60 transition-colors"
          style={{ padding: "0 8px" }}
        >
          <div
            className="rounded-full bg-accent-brand/20 border border-accent-brand/30 flex items-center justify-center font-bold text-accent-brand shrink-0"
            style={{ width: 24, height: 24, fontSize: 11 }}
          >
            {username.charAt(0).toUpperCase() || "U"}
          </div>
          <div
            className={`flex flex-col items-start overflow-hidden transition-opacity duration-150 ${
              railExpanded ? "opacity-100 delay-75" : "opacity-0"
            }`}
          >
            <span className="text-xs font-semibold leading-tight whitespace-nowrap">
              {username || "User"}
            </span>
            <span className="text-[10px] text-muted-foreground leading-tight whitespace-nowrap">
              {isAdmin ? t("nav.roleAdministrator") : t("nav.roleUser")}
            </span>
          </div>
        </button>
      </div>

      {menuPos && (
        <div
          data-rail-context-menu
          style={{ position: "fixed", left: menuPos.x, top: menuPos.y }}
          className="z-[10000] bg-popover border border-border shadow-lg py-1 min-w-[190px]"
        >
          {menuTarget && (
            <>
              {menuTarget.promotable && (
                <button
                  onClick={() => {
                    onOpenTab?.(menuTarget.view as TabType);
                    setMenuPos(null);
                  }}
                  className="flex items-center gap-2 w-full px-3 py-1.5 text-xs text-left hover:bg-accent hover:text-accent-foreground"
                >
                  <span className="shrink-0 w-3 flex items-center justify-center">
                    <SquareArrowOutUpRight className="size-3" />
                  </span>
                  {t("nav.openAsTab")}
                </button>
              )}
              {menuTarget.rightDockable && (
                <button
                  onClick={() => {
                    onOpenInRightDock?.(menuTarget.view);
                    setMenuPos(null);
                  }}
                  className="flex items-center gap-2 w-full px-3 py-1.5 text-xs text-left hover:bg-accent hover:text-accent-foreground"
                >
                  <span className="shrink-0 w-3 flex items-center justify-center">
                    <PanelRight className="size-3" />
                  </span>
                  {t("nav.openInRightDock")}
                </button>
              )}
              <div className="h-px bg-border my-1" />
            </>
          )}
          <button
            onClick={togglePinned}
            className="flex items-center gap-2 w-full px-3 py-1.5 text-xs text-left hover:bg-accent hover:text-accent-foreground"
            role="menuitemcheckbox"
            aria-checked={pinned}
          >
            <span className="shrink-0 w-3 flex items-center justify-center">
              {pinned && <Check className="size-3" />}
            </span>
            {t("newUi.sidebar.userProfile.pinAppRail")}
          </button>
          <button
            onClick={toggleExpandOnHover}
            className="flex items-center gap-2 w-full px-3 py-1.5 text-xs text-left hover:bg-accent hover:text-accent-foreground"
            role="menuitemcheckbox"
            aria-checked={expandOnHover}
          >
            <span className="shrink-0 w-3 flex items-center justify-center">
              {expandOnHover && <Check className="size-3" />}
            </span>
            {t("newUi.sidebar.userProfile.expandAppRailOnHover")}
          </button>
          <div className="h-px bg-border my-1" />
          <button
            onClick={() => {
              onRailClick("user-profile");
              setMenuPos(null);
            }}
            className="flex items-center gap-2 w-full px-3 py-1.5 text-xs text-left hover:bg-accent hover:text-accent-foreground"
          >
            <span className="shrink-0 w-3 flex items-center justify-center">
              <SlidersHorizontal className="size-3" />
            </span>
            {t("nav.sidebarSettings")}
          </button>
        </div>
      )}
    </div>
  );
}
