import type { ComponentChildren } from 'preact';
import { useEffect, useRef } from 'preact/hooks';
import { getI18n } from '../../core/i18n';
import { Field } from '../core/Field';
import { Input, type InputProps } from '../core/Input';
import { cn } from '../core/cn';

export function normalizeHexColor(value: unknown): string | null {
  const raw = String(value ?? '').trim();
  if (!raw) return null;

  const prefixed = raw.startsWith('#') ? raw : `#${raw}`;
  if (/^#[0-9a-f]{3}$/i.test(prefixed)) {
    return `#${prefixed
      .slice(1)
      .split('')
      .map((character) => `${character}${character}`)
      .join('')}`.toLowerCase();
  }

  return /^#[0-9a-f]{6}$/i.test(prefixed) ? prefixed.toLowerCase() : null;
}

export type ColorInputProps = Omit<InputProps, 'type' | 'value' | 'onInput' | 'onChange'> & {
  value: string;
  inputClassName?: string;
  textInputClassName?: string;
  wrapperClassName?: string;
  colorLabel?: string;
  onValueChange?: (value: string) => void;
  onValueCommit?: (value: string) => void;
};

export function ColorInput({
  value,
  inputClassName,
  textInputClassName,
  wrapperClassName,
  colorLabel,
  onValueChange,
  onValueCommit,
  required,
  compact,
  disabled,
  id,
  ...props
}: ColorInputProps) {
  const t = getI18n().t;
  const normalizedValue = normalizeHexColor(value) ?? '#000000';
  const textInputRef = useRef<HTMLInputElement | null>(null);
  const lastEmittedValue = useRef(normalizedValue);

  useEffect(() => {
    if (textInputRef.current) textInputRef.current.value = normalizedValue;
    lastEmittedValue.current = normalizedValue;
  }, [normalizedValue]);

  const applyDraft = (nextDraft: string, commit: boolean) => {
    const nextValue = normalizeHexColor(nextDraft);
    if (!nextValue) {
      if (commit && textInputRef.current) textInputRef.current.value = normalizedValue;
      return;
    }

    if (textInputRef.current) textInputRef.current.value = nextValue;
    if (nextValue !== lastEmittedValue.current) {
      lastEmittedValue.current = nextValue;
      onValueChange?.(nextValue);
    }
    if (commit) onValueCommit?.(nextValue);
  };

  const accessibleLabel = colorLabel || String(props['aria-label'] ?? t('common.color', 'Color'));

  return (
    <div className={cn('ask-color-input ask-w-full ask-min-w-0', wrapperClassName)} data-asuka-color-input>
      <Input
        {...props}
        id={id}
        required={required}
        disabled={disabled}
        aria-label={accessibleLabel}
        aria-required={required ? true : undefined}
        compact={compact}
        type="color"
        value={normalizedValue}
        className={cn(
          compact
            ? 'ask-h-8 ask-w-12 ask-shrink-0 ask-p-1'
            : 'ask-h-10 ask-w-14 ask-shrink-0 ask-p-1',
          inputClassName,
        )}
        onInput={(event: any) => applyDraft(String(event?.currentTarget?.value ?? normalizedValue), false)}
        onChange={(event: any) => applyDraft(String(event?.currentTarget?.value ?? normalizedValue), true)}
      />
      <Input
        inputRef={textInputRef}
        id={id ? `${id}-hex` : undefined}
        aria-label={t('form.color.hexLabel', '{label} hexadecimal', { label: accessibleLabel })}
        compact={compact}
        type="text"
        defaultValue={normalizedValue}
        disabled={disabled}
        maxLength={7}
        autoComplete="off"
        spellcheck={false}
        placeholder={t('form.color.hexPlaceholder', '#RRGGBB')}
        className={cn('ask-color-input__hex ask-min-w-0 ask-font-mono', textInputClassName)}
        onBlur={(event: any) => applyDraft(String(event?.currentTarget?.value ?? ''), true)}
        onKeyDown={(event: any) => {
          if (event.key === 'Enter') {
            event.preventDefault();
            applyDraft(String(event?.currentTarget?.value ?? ''), true);
          }
          if (event.key === 'Escape') {
            event.preventDefault();
            if (textInputRef.current) textInputRef.current.value = normalizedValue;
            event.currentTarget?.blur?.();
          }
        }}
      />
    </div>
  );
}

export type ColorFieldProps = Omit<ColorInputProps, 'colorLabel'> & {
  label?: string;
  hint?: string;
  right?: ComponentChildren;
  fieldClassName?: string;
};

export function ColorField({
  label,
  hint,
  right,
  value,
  fieldClassName,
  inputClassName,
  onValueChange,
  onValueCommit,
  required,
  compact,
  ...props
}: ColorFieldProps) {
  return (
    <Field
      label={label}
      hint={hint}
      right={right as any}
      required={Boolean(required)}
      className={fieldClassName}
      compact={compact}
    >
      <ColorInput
        {...props}
        colorLabel={label}
        required={required}
        compact={compact}
        value={value}
        inputClassName={inputClassName}
        onValueChange={onValueChange}
        onValueCommit={onValueCommit}
      />
    </Field>
  );
}
