import { useEffect, useRef, useState } from "react"

const SIDEBAR_KEY = "crema.shell.sidebar"
import { NavLink, useNavigate } from "react-router"
import {
  Bell,
  LayoutDashboard,
  Boxes,
  Activity,
  Building2,
  Sparkles,
  Bot,
  BookOpen,
  Settings,
  Search,
  PanelLeftClose,
  PanelLeftOpen,
  User as UserIcon,
  LogOut,
  HelpCircle,
  Menu,
  Play,
  HardDrive,
  Users as UsersIcon,
  KeyRound,
  Webhook as WebhookIcon,
  CalendarClock,
  // CREMA:NAV-ICONS
} from "lucide-react"

import {
  useBrand,
  useUser,
  type Brand,
  type User,
} from "~/lib/identity"

import {
  Appbar,
  AppbarActions,
  AppbarSpacer,
  AppbarTitle,
} from "~/components/layout/appbar"
import { ThemeToggle } from "~/components/layout/theme-toggle"
import { BackgroundPicker } from "~/components/layout/background-picker"
import { FontSizePicker } from "~/components/layout/font-size-picker"
import { SurfacePicker } from "~/components/layout/surface-picker"
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "~/components/ui/popover"
import { profileInitials, useProfile } from "~/lib/profile"
import { signOut, useSession } from "~/lib/session"
import {
  addNotification,
  dismiss,
  dismissAll,
  markAllRead,
  markRead,
  seedIfEmpty,
  unreadCount,
  useNotifications,
} from "~/lib/notifications"
import { Button } from "~/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu"
import { Input } from "~/components/ui/input"
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "~/components/ui/sheet"
import { ScriptsDialog, useScriptsHotkey } from "~/components/scripts-dialog"

type NavItem = {
  to: string
  icon: React.ComponentType<{ className?: string }>
  label: string
  end?: boolean
}

const navItems: NavItem[] = [
  { to: "/", icon: LayoutDashboard, label: "Overview", end: true },
  { to: "/tenants", icon: Building2, label: "Tenants" },
  { to: "/storage", icon: HardDrive, label: "Storage" },
  { to: "/users", icon: UsersIcon, label: "Users" },
  { to: "/secrets", icon: KeyRound, label: "Secrets" },
  { to: "/webhooks", icon: WebhookIcon, label: "Webhooks" },
  { to: "/scheduled-tasks", icon: CalendarClock, label: "Scheduled" },
  { to: "/activity", icon: Activity, label: "Audit log" },
  { to: "/ai", icon: Bot, label: "AI" },
  { to: "/settings", icon: Settings, label: "Settings" },
  // CREMA:NAV-ITEMS
]

type AppShellProps = {
  title: string
  children: React.ReactNode
  brand?: Brand
  user?: User
  /**
   * Optional theme name. When set, the shell wraps itself in
   * `data-theme={theme}` so a route can opt into an alternate theme without
   * the caller having to add an extra wrapping div.
   */
  theme?: string
}

export function AppShell({
  title,
  children,
  brand: brandOverride,
  user: userOverride,
  theme,
}: AppShellProps) {
  const defaultBrand = useBrand()
  const defaultUser = useUser()
  const profile = useProfile()
  const session = useSession()
  const navigate = useNavigate()
  const brand = brandOverride ?? defaultBrand
  // Prefer the live session for identity, fall back to the editable profile,
  // fall back to the stub user.
  const user = userOverride ?? {
    name: session?.name || profile.name || defaultUser.name,
    email: session?.email || profile.email || defaultUser.email,
    initials: profileInitials(
      session?.name || profile.name || defaultUser.name,
    ),
  }

  // Protected shell: bounce to /login when there's no session.
  useEffect(() => {
    if (typeof window === "undefined") return
    if (!session) {
      const next = encodeURIComponent(
        window.location.pathname + window.location.search,
      )
      navigate(`/login?next=${next}`, { replace: true })
    }
  }, [session, navigate])
  if (!session) return null
  const [expanded, setExpanded] = useState<boolean>(() => {
    if (typeof window === "undefined") return false
    return localStorage.getItem(SIDEBAR_KEY) === "1"
  })
  useEffect(() => {
    localStorage.setItem(SIDEBAR_KEY, expanded ? "1" : "0")
  }, [expanded])
  const [mobileOpen, setMobileOpen] = useState(false)
  const [scriptsOpen, setScriptsOpen] = useState(false)
  const BrandIcon = brand.icon

  useScriptsHotkey(() => setScriptsOpen(true))

  return (
    <div
      data-theme={theme}
      className="relative isolate flex min-h-svh"
    >
      <a
        href="#main-content"
        className="sr-only focus:not-sr-only focus:fixed focus:left-2 focus:top-2 focus:z-50 focus:rounded-md focus:bg-primary focus:px-3 focus:py-2 focus:text-primary-foreground focus:shadow-lg"
      >
        Skip to main content
      </a>
      <aside
        data-slot="sidebar"
        data-expanded={expanded ? "true" : "false"}
        className={[
          "sticky top-0 z-30 hidden h-svh shrink-0 flex-col border-r bg-sidebar transition-[width] duration-base ease-standard md:flex",
          expanded ? "w-60" : "w-16",
        ].join(" ")}
      >
        <div
          className={[
            "flex h-14 items-center gap-2 border-b px-3",
            expanded ? "justify-between" : "justify-center",
          ].join(" ")}
        >
          {expanded ? (
            <div className="flex items-center gap-2">
              <div className="flex size-8 items-center justify-center rounded-lg bg-primary text-primary-foreground">
                <BrandIcon className="size-4" />
              </div>
              <span className="font-heading font-semibold tracking-tight">
                {brand.name}
              </span>
            </div>
          ) : (
            <div className="flex size-8 items-center justify-center rounded-lg bg-primary text-primary-foreground">
              <BrandIcon className="size-4" />
            </div>
          )}
        </div>

        <nav className="flex min-h-0 flex-1 flex-col gap-1 overflow-y-auto p-2">
          {navItems.map((item) => {
            const Icon = item.icon
            return (
              <NavLink
                key={item.label}
                to={item.to}
                end={item.end}
                title={expanded ? undefined : item.label}
                data-action={`nav-${item.label.toLowerCase()}`}
                className={({ isActive }) =>
                  [
                    "flex items-center gap-3 rounded-lg px-3 py-2 font-medium transition-colors duration-fast ease-standard",
                    expanded ? "justify-start" : "justify-center",
                    isActive
                      ? "bg-primary/10 text-primary"
                      : "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
                  ].join(" ")
                }
              >
                <Icon className="size-5 shrink-0" />
                {expanded && <span className="truncate">{item.label}</span>}
              </NavLink>
            )
          })}
        </nav>

        <div className="shrink-0 border-t p-2">
          <Button
            data-action="sidebar-toggle"
            variant="ghost"
            size={expanded ? "sm" : "icon-sm"}
            onClick={() => setExpanded((v) => !v)}
            aria-label={expanded ? "Collapse sidebar" : "Expand sidebar"}
            className={expanded ? "w-full justify-start" : "w-full"}
          >
            {expanded ? (
              <>
                <PanelLeftClose className="size-4" />
                <span>Collapse</span>
              </>
            ) : (
              <PanelLeftOpen className="size-4" />
            )}
          </Button>
        </div>
      </aside>

      <main className="flex min-w-0 flex-1 flex-col">
        {/* Mobile-only menu trigger, floating top-left of main */}
        <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>
          <SheetTrigger
            data-action="mobile-nav-toggle"
            aria-label="Open navigation"
            className="fixed left-3 top-3 z-30 inline-flex size-9 items-center justify-center rounded-full border bg-card/70 text-muted-foreground shadow-sm backdrop-blur-md transition-colors hover:bg-accent hover:text-accent-foreground md:hidden"
          >
            <Menu className="size-5" />
          </SheetTrigger>
          <SheetContent side="left" className="w-72 p-0">
            <SheetHeader className="border-b">
              <SheetTitle className="flex items-center gap-2">
                <div className="flex size-7 items-center justify-center rounded-lg bg-primary text-primary-foreground">
                  <BrandIcon className="size-4" />
                </div>
                {brand.name}
              </SheetTitle>
            </SheetHeader>
            <nav className="flex flex-col gap-1 p-2">
              {navItems.map((item) => {
                const Icon = item.icon
                return (
                  <NavLink
                    key={item.label}
                    to={item.to}
                    end={item.end}
                    onClick={() => setMobileOpen(false)}
                    data-action={`nav-mobile-${item.label.toLowerCase()}`}
                    className={({ isActive }) =>
                      [
                        "flex items-center gap-3 rounded-lg px-3 py-2 font-medium transition-colors",
                        isActive
                          ? "bg-primary/10 text-primary"
                          : "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
                      ].join(" ")
                    }
                  >
                    <Icon className="size-5 shrink-0" />
                    <span>{item.label}</span>
                  </NavLink>
                )
              })}
            </nav>
          </SheetContent>
        </Sheet>

        {/* Floating glass pill, top-right, replacing the appbar action group */}
        <div
          data-slot="floating-actions"
          className="fixed right-3 top-3 z-30 flex items-center gap-0.5 rounded-full border bg-card/70 px-1.5 py-1 shadow-sm backdrop-blur-md"
        >
          <Button
            data-action="appbar-scripts"
            variant="ghost"
            size="icon-sm"
            aria-label="Run script (Cmd+Shift+P)"
            title="Run script (Cmd+Shift+P)"
            onClick={() => setScriptsOpen(true)}
          >
            <Play />
          </Button>
          <FontSizePicker />
          <SurfacePicker />
          <BackgroundPicker />
          <ThemeToggle />
          <NotificationsBell />
          <DropdownMenu>
            <DropdownMenuTrigger
              data-action="appbar-avatar"
              aria-label="Account menu"
              className="ml-1 rounded-full outline-none ring-offset-2 ring-offset-background transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-ring"
            >
              <Avatar className="size-7 cursor-pointer">
                {profile.avatarUrl ? (
                  <AvatarImage src={profile.avatarUrl} alt={user.name} />
                ) : null}
                <AvatarFallback>{user.initials}</AvatarFallback>
              </Avatar>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" sideOffset={8} className="w-56">
              <DropdownMenuGroup>
                <DropdownMenuLabel className="flex flex-col gap-0.5">
                  <span className="font-medium">{user.name}</span>
                  <span className="text-xs font-normal text-muted-foreground">
                    {user.email}
                  </span>
                </DropdownMenuLabel>
              </DropdownMenuGroup>
              <DropdownMenuSeparator />
              <DropdownMenuItem
                data-action="avatar-profile"
                onClick={() => navigate("/profile")}
              >
                <UserIcon /> Profile
              </DropdownMenuItem>
              <DropdownMenuItem
                data-action="avatar-settings"
                onClick={() => navigate("/settings")}
              >
                <Settings /> Settings
              </DropdownMenuItem>
              <DropdownMenuItem data-action="avatar-help">
                <HelpCircle /> Help
              </DropdownMenuItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem
                data-action="avatar-signout"
                variant="destructive"
                onClick={() => {
                  signOut()
                  navigate("/login", { replace: true })
                }}
              >
                <LogOut /> Sign out
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>

        <div
          id="main-content"
          tabIndex={-1}
          className="flex flex-1 flex-col gap-6 p-6 focus:outline-none"
        >
          {children}
        </div>
      </main>

      <ScriptsDialog open={scriptsOpen} onOpenChange={setScriptsOpen} />
      <NotificationDispatcher />
    </div>
  )
}

function NotificationDispatcher() {
  // Hidden bridge so the action bus can create real notifications:
  //   fill notify-title "Hello"
  //   fill notify-body "Body text"
  //   fill notify-kind "info"        # info|success|warning|error
  //   fill notify-href "/library"    # optional
  //   click notify-create
  const titleRef = useRef<HTMLInputElement>(null)
  const bodyRef = useRef<HTMLInputElement>(null)
  const kindRef = useRef<HTMLInputElement>(null)
  const hrefRef = useRef<HTMLInputElement>(null)
  const submit = () => {
    const title = titleRef.current?.value.trim() ?? ""
    if (!title) return
    const body = bodyRef.current?.value.trim() || undefined
    const rawKind = (kindRef.current?.value || "info").trim().toLowerCase()
    const kind = (
      ["info", "success", "warning", "error"].includes(rawKind)
        ? rawKind
        : "info"
    ) as "info" | "success" | "warning" | "error"
    const href = hrefRef.current?.value.trim() || undefined
    addNotification({ title, body, kind, href })
    if (titleRef.current) titleRef.current.value = ""
    if (bodyRef.current) bodyRef.current.value = ""
    if (kindRef.current) kindRef.current.value = ""
    if (hrefRef.current) hrefRef.current.value = ""
  }
  return (
    <div
      aria-hidden
      className="pointer-events-none fixed left-0 top-0 size-px overflow-hidden opacity-0"
    >
      <input
        ref={titleRef}
        data-action="notif-title"
        placeholder="title"
        aria-label="Notification title"
      />
      <input
        ref={bodyRef}
        data-action="notif-body"
        placeholder="body"
        aria-label="Notification body"
      />
      <input
        ref={kindRef}
        data-action="notif-kind"
        placeholder="info|success|warning|error"
        aria-label="Notification kind"
      />
      <input
        ref={hrefRef}
        data-action="notif-href"
        placeholder="/path (optional)"
        aria-label="Notification href"
      />
      <button
        type="button"
        data-action="notif-create"
        aria-label="Create notification"
        onClick={submit}
        className="pointer-events-auto"
      >
        create
      </button>
    </div>
  )
}

function NotificationsBell() {
  const items = useNotifications()
  const unread = unreadCount(items)
  const navigate = useNavigate()

  useEffect(() => {
    seedIfEmpty()
  }, [])

  return (
    <Popover>
      <PopoverTrigger
        render={
          <Button
            data-action="appbar-notifications"
            variant="ghost"
            size="icon-sm"
            aria-label="Notifications"
          >
            <span className="relative inline-flex">
              <Bell />
              {unread > 0 && (
                <span className="absolute -right-1 -top-1 inline-flex min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[9px] font-semibold text-primary-foreground">
                  {unread > 9 ? "9+" : unread}
                </span>
              )}
            </span>
          </Button>
        }
      />
      <PopoverContent align="end" className="w-80 p-0">
        <div className="flex items-center justify-between border-b px-3 py-2">
          <span className="text-sm font-semibold">Notifications</span>
          <div className="flex items-center gap-1">
            <Button
              data-action="notif-mark-all-read"
              variant="ghost"
              size="sm"
              onClick={() => markAllRead()}
              disabled={unread === 0}
            >
              Mark all read
            </Button>
            <Button
              data-action="notif-clear"
              variant="ghost"
              size="sm"
              onClick={() => dismissAll()}
              disabled={items.length === 0}
            >
              Clear
            </Button>
          </div>
        </div>
        <ul className="max-h-80 overflow-y-auto">
          {items.length === 0 ? (
            <li className="px-3 py-6 text-center text-sm text-muted-foreground">
              No notifications.
            </li>
          ) : (
            items.map((n) => (
              <li
                key={n.id}
                className={
                  "group flex items-start gap-2 border-b px-3 py-2 text-sm transition-colors hover:bg-accent/40 " +
                  (!n.readAt ? "bg-primary/5" : "")
                }
              >
                <span
                  className={
                    "mt-1 size-2 shrink-0 rounded-full " +
                    (n.kind === "success"
                      ? "bg-emerald-500"
                      : n.kind === "warning"
                        ? "bg-amber-500"
                        : n.kind === "error"
                          ? "bg-rose-500"
                          : "bg-primary")
                  }
                  aria-hidden
                />
                <button
                  type="button"
                  data-action={`notif-open-${n.id}`}
                  onClick={() => {
                    markRead(n.id)
                    if (n.href) navigate(n.href)
                  }}
                  className="flex flex-1 flex-col items-start text-left"
                >
                  <span className="font-medium">{n.title}</span>
                  {n.body && (
                    <span className="text-xs text-muted-foreground">
                      {n.body}
                    </span>
                  )}
                  <span className="text-[10px] text-muted-foreground/70">
                    {new Date(n.createdAt).toLocaleString()}
                  </span>
                </button>
                <button
                  type="button"
                  data-action={`notif-dismiss-${n.id}`}
                  onClick={() => dismiss(n.id)}
                  aria-label="Dismiss"
                  className="rounded p-1 text-muted-foreground opacity-0 hover:bg-background hover:text-foreground group-hover:opacity-100"
                >
                  <span aria-hidden>×</span>
                </button>
              </li>
            ))
          )}
        </ul>
      </PopoverContent>
    </Popover>
  )
}
