import { useEffect, useRef, useState } from 'react';
import type React from 'react';
import { useTranslation } from 'react-i18next';

import type { FeatureMeta } from '../../../types';
import { formatFilterValue, parseInputValue } from '../../../lib/format';

function EditableLabel({
  value,
  formatted,
  onCommit,
  prefix,
  suffix,
  className,
  style,
}: {
  value: number;
  formatted: string;
  onCommit: (v: number) => void;
  prefix?: string;
  suffix?: string;
  className?: string;
  style?: React.CSSProperties;
}) {
  const [editing, setEditing] = useState(false);
  const [text, setText] = useState('');
  const inputRef = useRef<HTMLInputElement>(null);

  const startEdit = () => {
    setEditing(true);
    setText(String(Math.round(value)));
  };

  const commit = () => {
    const parsed = parseInputValue(text, { prefix, suffix });
    if (parsed != null) onCommit(parsed);
    setEditing(false);
  };

  useEffect(() => {
    if (editing) {
      inputRef.current?.focus();
      inputRef.current?.select();
    }
  }, [editing]);

  if (editing) {
    return (
      <input
        ref={inputRef}
        value={text}
        onChange={(e) => setText(e.target.value)}
        onKeyDown={(e) => {
          if (e.key === 'Enter') commit();
          if (e.key === 'Escape') setEditing(false);
        }}
        onBlur={commit}
        className="absolute w-16 text-[10px] text-center rounded border border-warm-300 dark:border-warm-600 bg-white dark:bg-warm-800 text-warm-700 dark:text-warm-200 px-0.5 focus:outline-none focus:ring-1 focus:ring-teal-400"
        style={style}
      />
    );
  }

  return (
    <span
      className={`absolute cursor-pointer hover:text-teal-600 dark:hover:text-teal-400 border-b border-dotted border-warm-400 dark:border-warm-500 ${className ?? ''}`}
      style={style}
      onClick={startEdit}
    >
      {formatted}
    </span>
  );
}

export function SliderLabels({
  min,
  max,
  value,
  displayValues,
  isAtMin,
  isAtMax,
  raw,
  feature,
  showUnit,
  onValueChange,
}: {
  min: number;
  max: number;
  value: [number, number];
  displayValues?: [number, number];
  isAtMin?: boolean;
  isAtMax?: boolean;
  raw?: boolean;
  feature?: FeatureMeta;
  showUnit?: boolean;
  onValueChange?: (v: [number, number]) => void;
}) {
  const { t } = useTranslation();
  const range = max - min || 1;
  const leftPct = Math.max(0, Math.min(100, ((value[0] - min) / range) * 100));
  const rightPct = Math.max(0, Math.min(100, ((value[1] - min) / range) * 100));
  const labels = displayValues || value;
  const shouldShowUnit = Boolean(feature && (showUnit || feature.suffix === '%'));
  const labelFormat = shouldShowUnit
    ? { raw, prefix: feature?.prefix, suffix: feature?.suffix }
    : raw;

  const minLabel = isAtMin ? t('common.min') : formatFilterValue(labels[0], labelFormat);
  const maxLabel = isAtMax ? t('common.max') : formatFilterValue(labels[1], labelFormat);

  // Smoothly spread labels apart as thumbs get close to prevent overlap.
  // gapRatio=1 (centered) when far apart, gapRatio=0 (split) when touching.
  const SPREAD_THRESHOLD = 20; // percentage gap below which labels start separating
  const gapPct = rightPct - leftPct;
  const gapRatio = Math.min(1, Math.max(0, gapPct / SPREAD_THRESHOLD));
  const leftTranslate = `translateX(${-100 + gapRatio * 50}%)`;
  const rightTranslate = `translateX(${-gapRatio * 50}%)`;

  if (feature && onValueChange) {
    return (
      <div className="relative h-4 mt-2 mx-2.5 text-[10px] text-warm-500 dark:text-warm-400 leading-tight">
        <EditableLabel
          value={labels[0]}
          formatted={minLabel}
          onCommit={(v) => onValueChange([v, Math.max(v, labels[1])])}
          prefix={feature.prefix}
          suffix={feature.suffix}
          style={{ left: `${leftPct}%`, transform: leftTranslate }}
        />
        <EditableLabel
          value={labels[1]}
          formatted={maxLabel}
          onCommit={(v) => onValueChange([Math.min(labels[0], v), v])}
          prefix={feature.prefix}
          suffix={feature.suffix}
          style={{ left: `${rightPct}%`, transform: rightTranslate }}
        />
      </div>
    );
  }

  return (
    <div className="relative h-4 mt-2 mx-2.5 text-[10px] text-warm-500 dark:text-warm-400 leading-tight">
      <span className="absolute" style={{ left: `${leftPct}%`, transform: leftTranslate }}>
        {minLabel}
      </span>
      <span className="absolute" style={{ left: `${rightPct}%`, transform: rightTranslate }}>
        {maxLabel}
      </span>
    </div>
  );
}
