import { useEffect, useRef, useState } from "react";
import type { Editor as TiptapEditor } from "@tiptap/core";
import type { HocuspocusProvider } from "@hocuspocus/provider";
import {
  Undo2,
  Redo2,
  Settings,
  Upload,
  Eye,
  BarChart3,
  Sun,
  Moon,
  Menu,
  LogIn,
  LogOut,
  MoreHorizontal,
  FileText,
  Trash2,
  PencilLine,
  Lock,
} from "lucide-react";
import { Tooltip } from "./Tooltip";
import { SyncIndicator } from "./SyncIndicator";
import { ConnectedUsers } from "./ConnectedUsers";
import type { CollabUser } from "../utils/user";

interface TopBarProps {
  editorInstance: TiptapEditor | null;
  providerRef: { current: HocuspocusProvider | null };
  docName: string;
  theme: "light" | "dark";
  user: CollabUser;
  loginUrl: string | null;
  isAuthenticated: boolean;
  /**
   * True when the signed-in user has write access on the backing Space
   * (Space owner, or org member with a `write`/`admin` role, or
   * `contributor` with at least one write resource group). When false
   * the editor is effectively read-only: the backend rejects mutating
   * routes with 403, so we mirror that on the UI by surfacing a
   * "Read-only" badge and disabling the Publish action up front.
   * Defaults to true in callers so the UI is permissive until the
   * status endpoint answers.
   */
  canEdit?: boolean;
  /** True while any collaborator has a publish in progress. */
  isPublishing?: boolean;
  /** Name of the user who initiated the running publish, if known. */
  publishingUserName?: string | null;
  onToggleTheme: () => void;
  onOpenSettings: () => void;
  onOpenPublish: () => void;
  onOpenMobileToc: () => void;
  /**
   * Open the Embed Studio from the toolbar. Smart entry point: lands on
   * an existing chart when there is one, otherwise creates a new chart.
   */
  onOpenEmbedStudio: () => void;
}

/**
 * Top toolbar of the editor: TOC drawer button (mobile only via CSS),
 * undo/redo, article settings, preview, theme toggle, publish action, sync
 * indicator, and the current user chip / sign-in link.
 */
export function TopBar({
  editorInstance,
  providerRef,
  docName,
  theme,
  user,
  loginUrl,
  isAuthenticated,
  canEdit = true,
  isPublishing = false,
  publishingUserName = null,
  onToggleTheme,
  onOpenSettings,
  onOpenPublish,
  onOpenMobileToc,
  onOpenEmbedStudio,
}: TopBarProps) {
  const publishTooltip = !canEdit
    ? "Read-only access - you don't have write rights on this Space"
    : isPublishing
      ? publishingUserName
        ? `${publishingUserName} is publishing...`
        : "Publish in progress..."
      : "Publish article";

  const accessTooltip = canEdit
    ? "Editor access - you can write to this Space"
    : "Read-only access - ask an org admin to grant you a write role";

  // Dev / utility menu state (Load demo, Reset article). Kept out of
  // the slash menu so it doesn't clutter the authoring surface.
  const [devMenuOpen, setDevMenuOpen] = useState(false);
  const devMenuRef = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (!devMenuOpen) return;
    const onDocClick = (e: MouseEvent) => {
      if (!devMenuRef.current) return;
      if (!devMenuRef.current.contains(e.target as Node)) setDevMenuOpen(false);
    };
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") setDevMenuOpen(false);
    };
    document.addEventListener("mousedown", onDocClick);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDocClick);
      document.removeEventListener("keydown", onKey);
    };
  }, [devMenuOpen]);

  // Account dropdown on the user chip (Sign out).
  // Same outside-click + Escape behavior as devMenu, but with its
  // own ref so the two menus don't toggle each other.
  const [accountMenuOpen, setAccountMenuOpen] = useState(false);
  const accountMenuRef = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (!accountMenuOpen) return;
    const onDocClick = (e: MouseEvent) => {
      if (!accountMenuRef.current) return;
      if (!accountMenuRef.current.contains(e.target as Node))
        setAccountMenuOpen(false);
    };
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") setAccountMenuOpen(false);
    };
    document.addEventListener("mousedown", onDocClick);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDocClick);
      document.removeEventListener("keydown", onKey);
    };
  }, [accountMenuOpen]);

  const handleSignOut = async () => {
    setAccountMenuOpen(false);
    try {
      // POST (not GET) so this can't be triggered by a cross-site
      // <img src=...> trick. Backend clears the httpOnly cookie.
      await fetch("/api/auth/logout", {
        method: "POST",
        credentials: "same-origin",
      });
    } catch {
      // Best-effort: even if the network call fails, reloading the
      // page lands us back on the login screen if the cookie was
      // already cleared, or keeps the session if it wasn't. The user
      // can retry from there.
    }
    // Hard reload so the WS provider, agent chat sessions, and any
    // cached auth state are reset cleanly. A SPA-only state purge
    // would leave the HocuspocusProvider connected with stale auth.
    window.location.reload();
  };

  const handleLoadDemo = () => {
    setDevMenuOpen(false);
    window.dispatchEvent(new CustomEvent("load-demo-content"));
  };
  const handleReset = () => {
    setDevMenuOpen(false);
    if (
      window.confirm(
        "Reset the article? This wipes the document, banner, frontmatter and citations.",
      )
    ) {
      window.dispatchEvent(new CustomEvent("reset-article"));
    }
  };

  return (
    <div className="top-bar">
      <button
        className="icon-btn top-bar__toc-toggle"
        onClick={onOpenMobileToc}
        aria-label="Table of contents"
      >
        <Menu size={18} />
      </button>
      <Tooltip title="Undo">
        <button
          className="icon-btn"
          onClick={() => editorInstance?.commands.undo()}
          aria-label="Undo"
        >
          <Undo2 size={18} />
        </button>
      </Tooltip>
      <Tooltip title="Redo">
        <button
          className="icon-btn"
          onClick={() => editorInstance?.commands.redo()}
          aria-label="Redo"
        >
          <Redo2 size={18} />
        </button>
      </Tooltip>
      <span className="divider-v" />
      <Tooltip title="Article settings">
        <button
          className="icon-btn"
          onClick={onOpenSettings}
          aria-label="Article settings"
        >
          <Settings size={18} />
        </button>
      </Tooltip>
      <Tooltip title="Embed Studio (charts)">
        <button
          className="icon-btn"
          onClick={onOpenEmbedStudio}
          aria-label="Open Embed Studio"
        >
          <BarChart3 size={18} />
        </button>
      </Tooltip>
      <Tooltip title="Preview article">
        <button
          className="icon-btn"
          onClick={() => window.open(`/api/preview/${docName}`, "_blank")}
          aria-label="Preview article"
        >
          <Eye size={18} />
        </button>
      </Tooltip>
      <Tooltip title={theme === "dark" ? "Switch to light mode" : "Switch to dark mode"}>
        <button
          className="icon-btn"
          onClick={onToggleTheme}
          aria-label="Toggle theme"
        >
          {theme === "dark" ? <Sun size={18} /> : <Moon size={18} />}
        </button>
      </Tooltip>

      <div className="top-bar__menu" ref={devMenuRef}>
        <Tooltip title="More actions">
          <button
            className="icon-btn"
            onClick={() => setDevMenuOpen((v) => !v)}
            aria-label="More actions"
            aria-haspopup="menu"
            aria-expanded={devMenuOpen || undefined}
          >
            <MoreHorizontal size={18} />
          </button>
        </Tooltip>
        {devMenuOpen && (
          <div className="top-bar__menu-pop" role="menu">
            <button
              className="top-bar__menu-item"
              role="menuitem"
              onClick={handleLoadDemo}
            >
              <FileText size={14} />
              <span className="top-bar__menu-item-content">
                <span className="top-bar__menu-item-title">
                  Load demo content
                </span>
                <span className="top-bar__menu-item-desc">
                  Replace document with a full demo article
                </span>
              </span>
            </button>
            <button
              className="top-bar__menu-item top-bar__menu-item--danger"
              role="menuitem"
              onClick={handleReset}
            >
              <Trash2 size={14} />
              <span className="top-bar__menu-item-content">
                <span className="top-bar__menu-item-title">Reset article</span>
                <span className="top-bar__menu-item-desc">
                  Wipe document, banner, frontmatter, citations
                </span>
              </span>
            </button>
          </div>
        )}
      </div>

      <span className="divider-v" />
      <Tooltip title={publishTooltip}>
        <button
          className="icon-btn icon-btn--primary"
          onClick={onOpenPublish}
          aria-label="Publish article"
          disabled={isPublishing || !canEdit}
          aria-busy={isPublishing || undefined}
        >
          <Upload size={18} />
        </button>
      </Tooltip>
      <ConnectedUsers providerRef={providerRef} />
      <SyncIndicator editorInstance={editorInstance} providerRef={providerRef} />
      {loginUrl && !isAuthenticated ? (
        <a
          href={loginUrl}
          className="chip chip--login"
          style={{ marginLeft: 4, textDecoration: "none" }}
        >
          <LogIn size={14} />
          Sign in with HF
        </a>
      ) : (
        <>
          {isAuthenticated && (
            <Tooltip title={accessTooltip}>
              <span
                className={`chip chip--sm ${canEdit ? "chip--editor" : "chip--readonly"}`}
                style={{ marginLeft: 4 }}
                aria-label={canEdit ? "Editor access" : "Read-only access"}
              >
                {canEdit ? <PencilLine size={11} /> : <Lock size={11} />}
                {canEdit ? "Editor" : "Read-only"}
              </span>
            </Tooltip>
          )}
        <div
          className="top-bar__menu"
          ref={accountMenuRef}
          style={{ marginLeft: 4 }}
        >
          <button
            type="button"
            className="chip chip--clickable"
            style={{
              backgroundColor: user.color,
              color: "#000",
              border: "none",
              cursor: "pointer",
            }}
            onClick={() => setAccountMenuOpen((v) => !v)}
            aria-haspopup="menu"
            aria-expanded={accountMenuOpen || undefined}
            aria-label={`Signed in as ${user.name}. Open account menu.`}
            title={`Signed in as ${user.name}`}
          >
            {user.avatarUrl && <img src={user.avatarUrl} alt="" />}
            {user.name}
          </button>
          {accountMenuOpen && (
            <div className="top-bar__menu-pop" role="menu">
              <button
                className="top-bar__menu-item top-bar__menu-item--danger"
                role="menuitem"
                onClick={handleSignOut}
              >
                <LogOut size={14} />
                <span className="top-bar__menu-item-content">
                  <span className="top-bar__menu-item-title">Sign out</span>
                  <span className="top-bar__menu-item-desc">
                    Disconnect from Hugging Face on this device
                  </span>
                </span>
              </button>
            </div>
          )}
        </div>
        </>
      )}
    </div>
  );
}
