import { type ReactElement } from "react";
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
import { cn } from "@/lib/utils";

export type TabsProps = React.ComponentProps<typeof TabsPrimitive.Root> & {
  orientation?: "horizontal" | "vertical";
};

function Tabs({
  className,
  orientation = "horizontal",
  ...props
}: TabsProps): ReactElement {
  return (
    <TabsPrimitive.Root
      className={cn(
        "group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
        className,
      )}
      data-orientation={orientation}
      data-slot="tabs"
      {...props}
    />
  );
}

const tabsListVariants = cva(
  "group/tabs-list inline-flex items-center gap-1 rounded-none p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-9 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
  {
    variants: {
      variant: {
        default: "bg-muted",
        line: "bg-transparent p-0",
      },
      // How the list sizes itself and lays out its triggers:
      //  - fit    (default): hugs its content, centred (natural trigger widths).
      //  - fill:  spans the full width and stretches triggers equally (flex-1).
      //  - scroll: spans the full width but keeps triggers at natural width and
      //            scrolls horizontally when they overflow — for more tabs than
      //            fit (e.g. budget-bucket tabs on a narrow card). Scrollbar hidden.
      width: {
        fit: "w-fit justify-center",
        fill: "w-full justify-center",
        scroll:
          "w-full justify-start overflow-x-auto [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden",
      },
    },
    defaultVariants: {
      variant: "default",
      width: "fit",
    },
  },
);

export type TabsListProps = React.ComponentProps<typeof TabsPrimitive.List> &
  VariantProps<typeof tabsListVariants>;

function TabsList({
  className,
  variant = "default",
  width = "fit",
  ...props
}: TabsListProps): ReactElement {
  return (
    <TabsPrimitive.List
      className={cn(tabsListVariants({ variant, width }), className)}
      data-slot="tabs-list"
      data-variant={variant}
      data-width={width}
      {...props}
    />
  );
}

export type TabsTriggerProps = React.ComponentProps<typeof TabsPrimitive.Tab>;

function TabsTrigger({ className, ...props }: TabsTriggerProps): ReactElement {
  return (
    <TabsPrimitive.Tab
      className={cn(
        // Base layout & typography
        "relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 whitespace-nowrap",
        // Line variant fills the full height so the bottom-0 active indicator lands exactly on
        // the TabsList's border-b divider (the -1px inset is only needed by the filled pill).
        "group-data-[variant=line]/tabs-list:h-full",
        "rounded-none border border-transparent px-1.5 py-1 text-label-medium",
        "text-muted-foreground transition-all",
        // Scroll width: keep natural width (don't stretch equally) so the row overflows and scrolls
        "group-data-[width=scroll]/tabs-list:flex-none group-data-[width=scroll]/tabs-list:px-3",
        // Vertical orientation
        "group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start",
        // Hover & focus
        "hover:text-foreground",
        "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring",
        // Disabled
        "disabled:pointer-events-none disabled:opacity-50",
        // Active state — Default variant: primary/10 bg + subtle shadow
        // Base UI uses data-active attribute for the active/selected tab
        "data-active:bg-primary/10 data-active:text-foreground",
        "group-data-[variant=default]/tabs-list:data-active:shadow-sm",
        // Active state — Line variant: suppress bg & shadow
        "group-data-[variant=line]/tabs-list:data-active:bg-transparent",
        "group-data-[variant=line]/tabs-list:data-active:shadow-none",
        // Indicator pseudo-element (visible only for Line variant, active state)
        "after:absolute after:bg-primary after:opacity-0 after:transition-opacity",
        "group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-0 group-data-[orientation=horizontal]/tabs:after:h-0.5",
        "group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5",
        "group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
        // SVG icons
        "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
        className,
      )}
      data-slot="tabs-trigger"
      {...props}
    />
  );
}

export type TabsContentProps = React.ComponentProps<typeof TabsPrimitive.Panel>;

function TabsContent({ className, ...props }: TabsContentProps): ReactElement {
  return (
    <TabsPrimitive.Panel
      className={cn("flex-1 outline-none", className)}
      data-slot="tabs-content"
      {...props}
    />
  );
}

export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
