'use client';

import { classNames } from '@/lib/components/classNames';
import { useId, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';
import styles from './Tabs.module.css';

export interface TabItem {
  id: string;
  label: string;
  content: ReactNode;
  disabled?: boolean;
}

interface TabsProps {
  items: TabItem[];
  label: string;
  defaultActiveId?: string;
  activation?: 'automatic' | 'manual';
  className?: string;
}

export function Tabs({
  items,
  label,
  defaultActiveId,
  activation = 'automatic',
  className,
}: TabsProps) {
  const available = items.filter((item) => !item.disabled);
  const initial =
    defaultActiveId && available.some((item) => item.id === defaultActiveId)
      ? defaultActiveId
      : (available[0]?.id ?? '');
  const [activeId, setActiveId] = useState(initial);
  const [focusedId, setFocusedId] = useState(initial);
  const refs = useRef(new Map<string, HTMLButtonElement>());
  const prefix = useId().replaceAll(':', '');

  const focusByOffset = (currentId: string, offset: number) => {
    const currentIndex = available.findIndex((item) => item.id === currentId);
    if (currentIndex < 0 || available.length === 0) return;
    const next = available[(currentIndex + offset + available.length) % available.length];
    if (!next) return;
    setFocusedId(next.id);
    if (activation === 'automatic') setActiveId(next.id);
    refs.current.get(next.id)?.focus();
  };

  const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>, id: string) => {
    if (event.key === 'ArrowRight') {
      event.preventDefault();
      focusByOffset(id, document.documentElement.dir === 'rtl' ? -1 : 1);
    } else if (event.key === 'ArrowLeft') {
      event.preventDefault();
      focusByOffset(id, document.documentElement.dir === 'rtl' ? 1 : -1);
    } else if (event.key === 'Home') {
      event.preventDefault();
      const first = available[0];
      if (first) focusByOffset(first.id, 0);
    } else if (event.key === 'End') {
      event.preventDefault();
      const last = available.at(-1);
      if (last) focusByOffset(last.id, 0);
    } else if ((event.key === 'Enter' || event.key === ' ') && activation === 'manual') {
      event.preventDefault();
      setActiveId(id);
    }
  };

  return (
    <div className={classNames(styles.tabs, className)}>
      <div className={styles.list} role="tablist" aria-label={label}>
        {items.map((item) => {
          const selected = item.id === activeId;
          return (
            <button
              key={item.id}
              ref={(node) => {
                if (node) refs.current.set(item.id, node);
                else refs.current.delete(item.id);
              }}
              type="button"
              role="tab"
              id={`${prefix}-tab-${item.id}`}
              aria-controls={`${prefix}-panel-${item.id}`}
              aria-selected={selected}
              tabIndex={item.id === focusedId ? 0 : -1}
              disabled={item.disabled}
              className={styles.tab}
              onClick={() => {
                setFocusedId(item.id);
                setActiveId(item.id);
              }}
              onKeyDown={(event) => handleKeyDown(event, item.id)}
            >
              {item.label}
            </button>
          );
        })}
      </div>
      {items.map((item) => (
        <div
          key={item.id}
          role="tabpanel"
          id={`${prefix}-panel-${item.id}`}
          aria-labelledby={`${prefix}-tab-${item.id}`}
          hidden={item.id !== activeId}
          tabIndex={0}
          className={styles.panel}
        >
          {item.content}
        </div>
      ))}
    </div>
  );
}
