"use client";

import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import * as PopoverPrimitive from "@radix-ui/react-popover";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import * as SwitchPrimitive from "@radix-ui/react-switch";
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import * as SeparatorPrimitive from "@radix-ui/react-separator";
import { Check } from "lucide-react";
import { cn, initials } from "@/lib/utils";
import { avatarIndexFor } from "@/lib/avatars";
import { AvatarArt } from "./avatar-art";

const useIsoLayoutEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect;

// ── Tooltip ───────────────────────────────────────────────────
const TooltipProvider = TooltipPrimitive.Provider;
const TooltipRoot = TooltipPrimitive.Root;
const TooltipTrigger = TooltipPrimitive.Trigger;
const TooltipContent = React.forwardRef<React.ElementRef<typeof TooltipPrimitive.Content>, React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>>(({ className, sideOffset = 6, style, ...props }, ref) => (
  <TooltipPrimitive.Portal>
    <TooltipPrimitive.Content
      ref={ref}
      sideOffset={sideOffset}
      style={{ transformOrigin: "var(--radix-tooltip-content-transform-origin)", ...style }}
      className={cn("z-50 max-w-xs rounded-md bg-stone-900 px-2.5 py-1.5 text-xs text-stone-50 shadow-md data-[state=delayed-open]:animate-menu-in data-[state=instant-open]:animate-menu-in data-[state=closed]:animate-menu-out dark:bg-stone-100 dark:text-stone-900", className)}
      {...props}
    />
  </TooltipPrimitive.Portal>
));
TooltipContent.displayName = "TooltipContent";

function Tooltip({ content, children, side, delay = 300 }: { content: React.ReactNode; children: React.ReactNode; side?: "top" | "bottom" | "left" | "right"; delay?: number }) {
  if (!content) return <>{children}</>;
  return (
    <TooltipRoot delayDuration={delay}>
      <TooltipTrigger asChild>{children}</TooltipTrigger>
      <TooltipContent side={side}>{content}</TooltipContent>
    </TooltipRoot>
  );
}

// ── Popover ───────────────────────────────────────────────────
const Popover = PopoverPrimitive.Root;
const PopoverTrigger = PopoverPrimitive.Trigger;
const PopoverAnchor = PopoverPrimitive.Anchor;
const PopoverClose = PopoverPrimitive.Close;
const PopoverContent = React.forwardRef<React.ElementRef<typeof PopoverPrimitive.Content>, React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>>(({ className, align = "center", sideOffset = 6, style, ...props }, ref) => (
  <PopoverPrimitive.Portal>
    <PopoverPrimitive.Content
      ref={ref}
      align={align}
      sideOffset={sideOffset}
      style={{ transformOrigin: "var(--radix-popover-content-transform-origin)", ...style }}
      className={cn("z-50 w-72 rounded-xl border border-border bg-surface p-4 text-fg shadow-lg outline-none data-[state=open]:animate-menu-in data-[state=closed]:animate-menu-out", className)}
      {...props}
    />
  </PopoverPrimitive.Portal>
));
PopoverContent.displayName = "PopoverContent";

// ── Tabs ──────────────────────────────────────────────────────
const Tabs = TabsPrimitive.Root;

/**
 * Tab list with a sliding active indicator (underline for `line`, floating
 * pill for `pill`). The indicator is measured from the active trigger, so it
 * glides between tabs and follows the content while it scrolls.
 */
const TabsList = React.forwardRef<React.ElementRef<typeof TabsPrimitive.List>, React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> & { variant?: "line" | "pill" }>(({ className, variant = "line", children, ...props }, forwardedRef) => {
  const innerRef = React.useRef<HTMLDivElement | null>(null);
  const [ind, setInd] = React.useState<{ left: number; width: number } | null>(null);
  const setRefs = React.useCallback(
    (node: HTMLDivElement | null) => {
      innerRef.current = node;
      if (typeof forwardedRef === "function") forwardedRef(node);
      else if (forwardedRef) forwardedRef.current = node;
    },
    [forwardedRef]
  );
  useIsoLayoutEffect(() => {
    const el = innerRef.current;
    if (!el) return;
    const measure = () => {
      const active = el.querySelector<HTMLElement>('[role="tab"][data-state="active"]');
      if (!active) return setInd(null);
      setInd({ left: active.offsetLeft, width: active.offsetWidth });
    };
    measure();
    const mo = new MutationObserver(measure);
    mo.observe(el, { attributes: true, subtree: true, attributeFilter: ["data-state"], childList: true });
    const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(measure) : null;
    ro?.observe(el);
    if (document.fonts?.ready) document.fonts.ready.then(measure).catch(() => {});
    return () => {
      mo.disconnect();
      ro?.disconnect();
    };
  }, []);
  return (
    <TabsPrimitive.List
      ref={setRefs}
      className={cn(
        "relative flex min-w-0 max-w-full items-center gap-1 overflow-x-auto scrollbar-none",
        variant === "line" && "border-b border-border",
        variant === "pill" && "rounded-lg bg-surface-2 p-1",
        className
      )}
      data-variant={variant}
      data-indicator={ind ? "ready" : undefined}
      {...props}
    >
      {ind ? (
        <span
          aria-hidden
          className={cn(
            "pointer-events-none absolute transition-[left,width] duration-300 [transition-timing-function:var(--ease-out-expo)]",
            variant === "line" ? "bottom-[-1px] h-0.5 rounded-full bg-primary" : "inset-y-1 rounded-md bg-surface shadow-xs hairline-top"
          )}
          style={{ left: ind.left, width: ind.width }}
        />
      ) : null}
      {children}
    </TabsPrimitive.List>
  );
});
TabsList.displayName = "TabsList";
const TabsTrigger = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Trigger>, React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> & { count?: number }>(({ className, children, count, ...props }, ref) => (
  <TabsPrimitive.Trigger
    ref={ref}
    className={cn(
      "group relative z-[1] inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-sm font-medium text-fg-muted transition-colors duration-200 outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50",
      "[[data-variant=line]_&]:-mb-px [[data-variant=line]_&]:border-b-2 [[data-variant=line]_&]:border-transparent [[data-variant=line]_&]:px-3 [[data-variant=line]_&]:py-2.5 [[data-variant=line]_&]:hover:text-fg [[data-variant=line]_&]:data-[state=active]:text-fg",
      "[[data-variant=line]:not([data-indicator])_&]:data-[state=active]:border-primary",
      "[[data-variant=pill]_&]:rounded-md [[data-variant=pill]_&]:px-3 [[data-variant=pill]_&]:py-1.5 [[data-variant=pill]_&]:hover:text-fg [[data-variant=pill]_&]:data-[state=active]:text-fg",
      "[[data-variant=pill]:not([data-indicator])_&]:data-[state=active]:bg-surface [[data-variant=pill]:not([data-indicator])_&]:data-[state=active]:shadow-xs",
      className
    )}
    {...props}
  >
    {children}
    {count !== undefined ? <span className="rounded-full bg-surface-3 px-1.5 py-0.5 text-2xs tabular text-fg-muted transition-colors group-data-[state=active]:bg-primary/10 group-data-[state=active]:text-primary">{count}</span> : null}
  </TabsPrimitive.Trigger>
));
TabsTrigger.displayName = "TabsTrigger";
const TabsContent = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Content>, React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>>(({ className, ...props }, ref) => (
  <TabsPrimitive.Content ref={ref} className={cn("mt-4 outline-none animate-slide-up", className)} {...props} />
));
TabsContent.displayName = "TabsContent";

// ── Checkbox / Switch ─────────────────────────────────────────
const Checkbox = React.forwardRef<React.ElementRef<typeof CheckboxPrimitive.Root>, React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>>(({ className, ...props }, ref) => (
  <CheckboxPrimitive.Root
    ref={ref}
    className={cn("peer size-4 shrink-0 rounded-[4px] border border-border-strong bg-surface shadow-xs transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring active:scale-90 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-fg", className)}
    {...props}
  >
    <CheckboxPrimitive.Indicator className="flex items-center justify-center text-current animate-badge-pop">
      <Check className="size-3 stroke-[3]" />
    </CheckboxPrimitive.Indicator>
  </CheckboxPrimitive.Root>
));
Checkbox.displayName = "Checkbox";

const Switch = React.forwardRef<React.ElementRef<typeof SwitchPrimitive.Root>, React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> & { size?: "sm" | "md" }>(({ className, size = "md", ...props }, ref) => (
  <SwitchPrimitive.Root
    className={cn(
      "peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-border-strong",
      size === "md" ? "h-5 w-9" : "h-4 w-7",
      className
    )}
    {...props}
    ref={ref}
  >
    <SwitchPrimitive.Thumb className={cn("pointer-events-none block rounded-full bg-white shadow-sm ring-0 transition-transform duration-300 [transition-timing-function:var(--ease-spring)]", size === "md" ? "size-4 data-[state=checked]:translate-x-4" : "size-3 data-[state=checked]:translate-x-3", "data-[state=unchecked]:translate-x-0")} />
  </SwitchPrimitive.Root>
));
Switch.displayName = "Switch";

// ── Avatar ────────────────────────────────────────────────────
const AVATAR_COLORS = ["bg-brand-100 text-brand-800", "bg-accent-100 text-accent-700", "bg-gold-100 text-gold-700", "bg-info-100 text-info-700", "bg-positive-100 text-positive-700", "bg-warning-100 text-warning-700"];
function colorFor(name: string) {
  let h = 0;
  for (const ch of name) h = (h * 31 + ch.charCodeAt(0)) % 997;
  return AVATAR_COLORS[h % AVATAR_COLORS.length];
}
/**
 * `seed` (a guest id) or `avatar` (a chosen design) switches this from
 * initials to one of the 100 drawn guest avatars. Staff keep initials on
 * purpose — you recognise colleagues by them.
 */
function Avatar({ name, src, size = "md", className, online, seed, avatar }: { name: string; src?: string | null; size?: "xs" | "sm" | "md" | "lg" | "xl"; className?: string; online?: boolean | null; seed?: string | null; avatar?: number | null }) {
  const sz = { xs: "size-6 text-2xs", sm: "size-7 text-xs", md: "size-9 text-xs", lg: "size-12 text-sm", xl: "size-16 text-lg" }[size];
  const art = avatar ?? (seed ? avatarIndexFor(seed) : null);
  return (
    <span className={cn("relative inline-flex shrink-0", className)}>
      <AvatarPrimitive.Root className={cn("inline-flex items-center justify-center overflow-hidden rounded-full font-semibold select-none", sz, art === null && colorFor(name))}>
        {src ? <AvatarPrimitive.Image src={src} alt={name} className="size-full object-cover" /> : null}
        <AvatarPrimitive.Fallback delayMs={src ? 300 : 0} className="flex size-full items-center justify-center">
          {art === null ? initials(name) : <AvatarArt index={art} className="size-full" />}
        </AvatarPrimitive.Fallback>
      </AvatarPrimitive.Root>
      {online !== undefined && online !== null ? (
        <span className={cn("absolute -bottom-0 -right-0 rounded-full ring-2 ring-surface transition-colors", size === "xs" || size === "sm" ? "size-2" : "size-2.5", online ? "bg-positive-500" : "bg-stone-400")} title={online ? "Online" : "Offline"} />
      ) : null}
    </span>
  );
}

// ── Separator ─────────────────────────────────────────────────
const Separator = React.forwardRef<React.ElementRef<typeof SeparatorPrimitive.Root>, React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
  <SeparatorPrimitive.Root ref={ref} decorative={decorative} orientation={orientation} className={cn("shrink-0 bg-border", orientation === "horizontal" ? "h-px w-full" : "h-full w-px", className)} {...props} />
));
Separator.displayName = "Separator";

// ── Progress ──────────────────────────────────────────────────
function Progress({ value, className, tone = "primary", size = "md" }: { value: number; className?: string; tone?: "primary" | "positive" | "warning" | "negative" | "info"; size?: "sm" | "md" }) {
  const bar = { primary: "bg-primary", positive: "bg-positive-500", warning: "bg-warning-500", negative: "bg-negative-500", info: "bg-info-500" }[tone];
  return (
    <div className={cn("w-full overflow-hidden rounded-full bg-surface-3", size === "md" ? "h-2" : "h-1.5", className)} role="progressbar" aria-valuenow={value} aria-valuemin={0} aria-valuemax={100}>
      <div className={cn("h-full rounded-full transition-[width] duration-700 [transition-timing-function:var(--ease-out-expo)]", bar)} style={{ width: `${Math.min(100, Math.max(0, value))}%` }} />
    </div>
  );
}

export { TooltipProvider, Tooltip, TooltipRoot, TooltipTrigger, TooltipContent, Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverClose, Tabs, TabsList, TabsTrigger, TabsContent, Checkbox, Switch, Avatar, Separator, Progress };
