"use client";

import {
  createContext,
  useCallback,
  useContext,
  useId,
  useState,
  type HTMLAttributes,
  type KeyboardEvent,
  type ReactNode,
} from "react";
import { cn } from "@/lib/utils";

interface TabsContextValue {
  activeId: string;
  setActiveId: (id: string) => void;
  baseId: string;
}

const TabsContext = createContext<TabsContextValue | null>(null);

function useTabsContext() {
  const ctx = useContext(TabsContext);
  if (!ctx) {
    throw new Error("Tabs components must be used within <Tabs>");
  }
  return ctx;
}

export interface TabsProps extends HTMLAttributes<HTMLDivElement> {
  defaultValue: string;
  value?: string;
  onValueChange?: (value: string) => void;
  children: ReactNode;
}

export function Tabs({
  defaultValue,
  value,
  onValueChange,
  className,
  children,
  ...props
}: TabsProps) {
  const baseId = useId();
  const [internalValue, setInternalValue] = useState(defaultValue);
  const activeId = value ?? internalValue;

  const setActiveId = useCallback(
    (id: string) => {
      if (value === undefined) {
        setInternalValue(id);
      }
      onValueChange?.(id);
    },
    [onValueChange, value],
  );

  return (
    <TabsContext.Provider value={{ activeId, setActiveId, baseId }}>
      <div className={cn("w-full", className)} {...props}>
        {children}
      </div>
    </TabsContext.Provider>
  );
}

export interface TabItem {
  id: string;
  label: string;
  disabled?: boolean;
}

export interface TabsListProps extends HTMLAttributes<HTMLDivElement> {
  items: TabItem[];
}

export function TabsList({ items, className, ...props }: TabsListProps) {
  const { activeId, setActiveId, baseId } = useTabsContext();

  const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>, index: number) => {
    const enabled = items.filter((item) => !item.disabled);
    const currentIndex = enabled.findIndex((item) => item.id === items[index].id);
    if (currentIndex < 0) return;

    let nextIndex = currentIndex;
    if (event.key === "ArrowRight") {
      nextIndex = (currentIndex + 1) % enabled.length;
    } else if (event.key === "ArrowLeft") {
      nextIndex = (currentIndex - 1 + enabled.length) % enabled.length;
    } else {
      return;
    }

    event.preventDefault();
    setActiveId(enabled[nextIndex].id);
    document.getElementById(`${baseId}-tab-${enabled[nextIndex].id}`)?.focus();
  };

  return (
    <div
      role="tablist"
      className={cn(
        "flex gap-1 overflow-x-auto border-b border-border",
        className,
      )}
      {...props}
    >
      {items.map((item, index) => {
        const selected = activeId === item.id;
        return (
          <button
            key={item.id}
            id={`${baseId}-tab-${item.id}`}
            type="button"
            role="tab"
            aria-selected={selected}
            aria-controls={`${baseId}-panel-${item.id}`}
            disabled={item.disabled}
            tabIndex={selected ? 0 : -1}
            onClick={() => setActiveId(item.id)}
            onKeyDown={(event) => handleKeyDown(event, index)}
            className={cn(
              "min-h-11 shrink-0 cursor-pointer px-4 py-2.5",
              "font-inter text-sm font-medium transition-colors duration-200",
              "border-b-2 -mb-px",
              "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-green-deep focus-visible:ring-offset-2",
              "motion-reduce:transition-none",
              "disabled:cursor-not-allowed disabled:opacity-50",
              selected
                ? "border-brand-green text-brand-green"
                : "border-transparent text-muted hover:text-ink",
            )}
          >
            {item.label}
          </button>
        );
      })}
    </div>
  );
}

export interface TabsPanelProps extends HTMLAttributes<HTMLDivElement> {
  value: string;
  children: ReactNode;
}

export function TabsPanel({ value, children, className, ...props }: TabsPanelProps) {
  const { activeId, baseId } = useTabsContext();
  const selected = activeId === value;

  return (
    <div
      id={`${baseId}-panel-${value}`}
      role="tabpanel"
      aria-labelledby={`${baseId}-tab-${value}`}
      hidden={!selected}
      className={cn("pt-4", className)}
      {...props}
    >
      {selected ? children : null}
    </div>
  );
}
