import { forwardRef, useId } from 'react';
import styled from 'styled-components';
import { normalizeHexColor } from '@/shared/utils/color';

export interface ColorPickerProps {
  label?: string;
  value: string;
  onChange?: (value: string) => void;
  error?: string;
  hint?: string;
  fullWidth?: boolean;
  disabled?: boolean;
  id?: string;
}

const PickerWrapper = styled.div<{ $fullWidth?: boolean }>`
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  width: ${({ $fullWidth }) => ($fullWidth ? '100%' : 'auto')};
`;

const Label = styled.label<{ $hasError?: boolean }>`
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  font-weight: ${({ theme }) => theme.typography.fontWeight.medium};
  color: ${({ theme, $hasError }) => ($hasError ? theme.colors.error : theme.colors.gray[600])};
`;

const ControlRow = styled.div`
  display: flex;
  align-items: center;
  gap: ${({ theme }) => theme.spacing[3]};
`;

const NativeColorInput = styled.input<{ $hasError?: boolean; $readOnly?: boolean }>`
  width: 3rem;
  height: 2.5rem;
  padding: 0.25rem;
  border: 1px solid
    ${({ theme, $hasError }) => ($hasError ? theme.colors.error : theme.colors.gray[200])};
  border-radius: ${({ theme }) => theme.borderRadius.md};
  background-color: ${({ theme }) => theme.colors.surface};
  cursor: ${({ $readOnly }) => ($readOnly ? 'default' : 'pointer')};
  transition: border-color ${({ theme }) => theme.transitions.fast};

  &::-webkit-color-swatch-wrapper {
    padding: 0;
  }

  &::-webkit-color-swatch {
    border: none;
    border-radius: calc(${({ theme }) => theme.borderRadius.md} - 2px);
  }

  &::-moz-color-swatch {
    border: none;
    border-radius: calc(${({ theme }) => theme.borderRadius.md} - 2px);
  }

  &:hover:not(:disabled) {
    border-color: ${({ theme, $hasError }) =>
      $hasError ? theme.colors.error : theme.colors.gray[300]};
  }

  &:focus {
    outline: none;
    border-color: ${({ theme, $hasError }) =>
      $hasError ? theme.colors.error : theme.colors.primary};
    box-shadow: 0 0 0 3px
      ${({ theme, $hasError }) => ($hasError ? `${theme.colors.error}33` : `${theme.colors.primary}33`)};
  }

  &:disabled {
    opacity: 0.7;
    cursor: not-allowed;
  }
`;

const ValueText = styled.span`
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  font-family: ${({ theme }) => theme.typography.fontFamily.mono};
  color: ${({ theme }) => theme.colors.text.secondary};
`;

const HintText = styled.span<{ $isError?: boolean }>`
  font-size: ${({ theme }) => theme.typography.fontSize.xs};
  color: ${({ theme, $isError }) => ($isError ? theme.colors.error : theme.colors.gray[500])};
`;

export const ColorPicker = forwardRef<HTMLInputElement, ColorPickerProps>(
  ({ label, value, onChange, error, hint, fullWidth, disabled, id }, ref) => {
    const generatedId = useId();
    const inputId = id ?? generatedId;
    const normalizedValue = normalizeHexColor(value);

    return (
      <PickerWrapper $fullWidth={fullWidth}>
        {label && (
          <Label htmlFor={inputId} $hasError={!!error}>
            {label}
          </Label>
        )}
        <ControlRow>
          <NativeColorInput
            ref={ref}
            id={inputId}
            type="color"
            value={normalizedValue}
            disabled={disabled}
            $hasError={!!error}
            $readOnly={disabled}
            aria-label={label}
            onChange={(event) => onChange?.(event.target.value.toUpperCase())}
          />
          <ValueText aria-hidden="true">{normalizedValue}</ValueText>
        </ControlRow>
        {(error || hint) && <HintText $isError={!!error}>{error || hint}</HintText>}
      </PickerWrapper>
    );
  },
);

ColorPicker.displayName = 'ColorPicker';
