/**
 * SegmentedControl Component
 *
 * Theme-agnostic segmented control (radio group) with keyboard navigation.
 * Implements WCAG 2.1 AA accessibility with roving tabindex pattern.
 */

import { useRef, useCallback } from 'react';
import type { ReactNode, KeyboardEvent } from 'react';

import styled, { css } from 'styled-components';
import type { ThemeInterface } from '@lilith/ui-theme';

export interface SegmentedControlOption<T extends string = string> {
  value: T;
  label: string;
  icon?: ReactNode;
  disabled?: boolean;
}

export interface SegmentedControlProps<T extends string = string> {
  value: T;
  onChange: (value: T) => void;
  options: Array<SegmentedControlOption<T>>;
  size?: 'sm' | 'md';
  disabled?: boolean;
  'aria-label': string;
  className?: string;
}

const Container = styled.div<{ $size: 'sm' | 'md' }>`
  display: inline-flex;
  align-items: stretch;
  border: 2px solid ${(props: { theme: ThemeInterface }) => props.theme.colors.border};
  border-radius: ${(props: { theme: ThemeInterface }) => props.theme.borderRadius.lg};
  overflow: hidden;
  background-color: ${(props) =>
    typeof props.theme.colors.background === 'object'
      ? props.theme.colors.background.secondary
      : props.theme.colors.surface};
  transition: border-color ${(props: { theme: ThemeInterface }) => props.theme.transitions.normal};

  &:focus-within {
    border-color: ${(props: { theme: ThemeInterface }) => props.theme.colors.primary};
    box-shadow: 0 0 0 2px ${(props: { theme: ThemeInterface }) => props.theme.colors.primary}33;
  }
`;

const OptionButton = styled.button<{
  $active: boolean;
  $size: 'sm' | 'md';
  $hasIcon: boolean;
}>`
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: ${(props: { theme: ThemeInterface }) => props.theme.typography.fontFamily.body};
  font-weight: ${(props: { theme: ThemeInterface }) => props.theme.typography.fontWeight.medium};
  text-align: center;
  cursor: pointer;
  border: none;
  border-right: 1px solid ${(props: { theme: ThemeInterface }) => props.theme.colors.border};
  transition: all ${(props: { theme: ThemeInterface }) => props.theme.transitions.normal};
  white-space: nowrap;
  flex-shrink: 0;

  &:last-child {
    border-right: none;
  }

  /* Size variants */
  ${({ $size, $hasIcon, theme }) => {
    switch ($size) {
      case 'sm':
        return css`
          padding: ${$hasIcon
            ? `${theme.spacing.xs} ${theme.spacing.sm}`
            : `${theme.spacing.xs} ${theme.spacing.md}`};
          font-size: ${theme.typography.fontSize.sm};
          gap: ${theme.spacing.xs};
          min-height: 32px;
        `;
      case 'md':
        return css`
          padding: ${$hasIcon
            ? `${theme.spacing.sm} ${theme.spacing.md}`
            : `${theme.spacing.sm} ${theme.spacing.lg}`};
          font-size: ${theme.typography.fontSize.base};
          gap: ${theme.spacing.sm};
          min-height: 40px;
        `;
      default:
        return css`
          padding: ${theme.spacing.sm} ${theme.spacing.md};
          font-size: ${theme.typography.fontSize.base};
          gap: ${theme.spacing.sm};
          min-height: 40px;
        `;
    }
  }}

  /* Active/Inactive states */
  ${({ $active, theme }) =>
    $active
      ? css`
          background-color: ${theme.colors.primary};
          color: ${typeof theme.colors.background === 'object'
            ? theme.colors.background.primary
            : theme.colors.text.primary};
          font-weight: ${theme.typography.fontWeight.semibold};

          ${theme.extensions?.cyberpunk &&
          css`
            box-shadow: inset 0 0 10px ${theme.colors.primary}33;
          `}
        `
      : css`
          background-color: transparent;
          color: ${theme.colors.text.secondary};

          &:hover:not(:disabled) {
            background-color: ${typeof theme.colors.background === 'object'
              ? theme.colors.background.tertiary
              : theme.colors.hover.surface};
            color: ${theme.colors.text.primary};
          }

          &:active:not(:disabled) {
            background-color: ${theme.colors.hover.primary};
          }
        `}

  /* Disabled state */
  &:disabled {
    cursor: not-allowed;
    opacity: 0.5;
    color: ${(props: { theme: ThemeInterface }) => props.theme.colors.disabled.text};

    &:hover {
      background-color: transparent;
    }
  }

  /* Focus state (visible only for keyboard navigation) */
  &:focus-visible {
    outline: 2px solid ${(props: { theme: ThemeInterface }) => props.theme.colors.primary};
    outline-offset: -2px;
    z-index: 1;
  }

  /* Remove default focus outline (replaced by focus-visible) */
  &:focus {
    outline: none;
  }
`;

const IconWrapper = styled.span<{ $size: 'sm' | 'md' }>`
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  ${({ $size }) =>
    $size === 'sm'
      ? css`
          width: 16px;
          height: 16px;
        `
      : css`
          width: 20px;
          height: 20px;
        `}

  svg {
    width: 100%;
    height: 100%;
  }
`;

const Label = styled.span`
  /* Text is always visible in SegmentedControl */
`;

/**
 * SegmentedControl component with full keyboard navigation support.
 *
 * Implements roving tabindex pattern for arrow key navigation:
 * - Left/Right arrows move focus
 * - Space/Enter select option
 * - Tab moves to next focusable element
 *
 * @example
 * // Basic usage
 * <SegmentedControl
 *   value={view}
 *   onChange={setView}
 *   options={[
 *     { value: 'grid', label: 'Grid' },
 *     { value: 'list', label: 'List' },
 *   ]}
 *   aria-label="View mode"
 * />
 *
 * @example
 * // With icons
 * <SegmentedControl
 *   value={theme}
 *   onChange={setTheme}
 *   options={[
 *     { value: 'light', label: 'Light', icon: <SunIcon /> },
 *     { value: 'dark', label: 'Dark', icon: <MoonIcon /> },
 *   ]}
 *   size="sm"
 *   aria-label="Theme selection"
 * />
 */
export const SegmentedControl = <T extends string = string>({
  value,
  onChange,
  options,
  size = 'md',
  disabled = false,
  className,
  'aria-label': ariaLabel,
}: SegmentedControlProps<T>) => {
  const containerRef = useRef<HTMLDivElement>(null);

  const handleKeyDown = useCallback(
    (event: KeyboardEvent<HTMLButtonElement>, currentValue: T) => {
      const currentIndex = options.findIndex((opt) => opt.value === currentValue);

      switch (event.key) {
        case 'ArrowLeft':
        case 'ArrowUp': {
          event.preventDefault();
          // Find previous enabled option
          let prevIndex = currentIndex - 1;

          while (prevIndex >= 0 && prevIndex < options.length) {
            const prevOption = options[prevIndex];
            if (prevOption && !prevOption.disabled) {
              onChange(prevOption.value);
              break;
            }

            prevIndex--;
          }

          break;
        }

        case 'ArrowRight':
        case 'ArrowDown': {
          event.preventDefault();
          // Find next enabled option
          let nextIndex = currentIndex + 1;

          while (nextIndex >= 0 && nextIndex < options.length) {
            const nextOption = options[nextIndex];
            if (nextOption && !nextOption.disabled) {
              onChange(nextOption.value);
              break;
            }

            nextIndex++;
          }

          break;
        }

        case 'Home': {
          event.preventDefault();
          // Find first enabled option
          const firstEnabled = options.find((opt) => !opt.disabled);

          if (firstEnabled) {
            onChange(firstEnabled.value);
          }

          break;
        }

        case 'End': {
          event.preventDefault();
          // Find last enabled option
          const reversedOptions = [...options].reverse();
          const lastEnabled = reversedOptions.find((opt) => !opt.disabled);

          if (lastEnabled) {
            onChange(lastEnabled.value);
          }

          break;
        }

        default:
          break;
      }
    },
    [options, onChange],
  );

  const handleClick = useCallback(
    (optionValue: T, optionDisabled?: boolean) => {
      if (disabled || optionDisabled) {
        return;
      }

      onChange(optionValue);
    },
    [disabled, onChange],
  );

  return (
    <Container
      ref={containerRef}
      role="radiogroup"
      aria-label={ariaLabel}
      $size={size}
      className={className}
    >
      {options.map((option) => {
        const isActive = option.value === value;
        const isDisabled = disabled || option.disabled;

        return (
          <OptionButton
            key={option.value}
            type="button"
            role="radio"
            aria-checked={isActive}
            aria-disabled={isDisabled}
            disabled={isDisabled}
            tabIndex={isActive ? 0 : -1}
            $active={isActive}
            $size={size}
            $hasIcon={!!option.icon}
            onClick={() => handleClick(option.value, option.disabled)}
            onKeyDown={(e) => handleKeyDown(e, option.value)}
          >
            {option.icon && <IconWrapper $size={size}>{option.icon}</IconWrapper>}
            <Label>{option.label}</Label>
          </OptionButton>
        );
      })}
    </Container>
  );
};
