// frontend\src\components\ui\Slider.tsx

'use client'

import { useId, type SyntheticEvent, type CSSProperties } from 'react'

type Props = {
  id?: string

  value: number
  onChange: (value: number) => void
  onChangeEnd?: (value: number) => void

  min?: number
  max?: number
  step?: number
  disabled?: boolean

  label?: string
  hint?: string

  valueLabel?: string
  valueFormatter?: (value: number) => string
  showValueLabel?: boolean

  showMinMaxLabels?: boolean
  minLabel?: string
  maxLabel?: string

  showReset?: boolean
  resetValue?: number
  resetLabel?: string

  compact?: boolean

  className?: string
  inputClassName?: string
}

function clamp(value: number, min: number, max: number) {
  return Math.max(min, Math.min(max, value))
}

export default function Slider({
  id,
  value,
  onChange,
  onChangeEnd,
  min = 0,
  max = 100,
  step = 1,
  disabled = false,
  label,
  hint,
  valueLabel,
  valueFormatter,
  showValueLabel = false,
  showMinMaxLabels = false,
  minLabel,
  maxLabel,
  showReset = false,
  resetValue,
  resetLabel = 'Reset',
  compact = false,
  className = '',
  inputClassName = '',
}: Props) {
  const reactId = useId()
  const inputId = id ?? `slider-${reactId}`

  const safeValue = Number.isFinite(value) ? value : min
  const clamped = clamp(safeValue, min, max)
  const percent = max > min ? ((clamped - min) / (max - min)) * 100 : 0

  const resolvedValueLabel =
    valueLabel ?? (valueFormatter ? valueFormatter(clamped) : String(clamped))

  const resolvedMinLabel =
    minLabel ?? (valueFormatter ? valueFormatter(min) : String(min))

  const resolvedMaxLabel =
    maxLabel ?? (valueFormatter ? valueFormatter(max) : String(max))

  const canReset =
    showReset &&
    typeof resetValue === 'number' &&
    Number.isFinite(resetValue)

  const trackH = compact ? 4 : 8
  const thumbSize = compact ? 14 : 16
  const inputH = compact ? 14 : 16
  const thumbOffset = -((thumbSize - trackH) / 2)

  const handleChange = (next: number) => {
    onChange(clamp(next, min, max))
  }

  const handleCommit = (e: SyntheticEvent<HTMLInputElement>) => {
    onChangeEnd?.(clamp(Number(e.currentTarget.value), min, max))
  }

  const handleReset = () => {
    if (!canReset) return
    const next = clamp(resetValue!, min, max)
    onChange(next)
    onChangeEnd?.(next)
  }

  return (
    <div
      className={[
        compact
          ? 'flex w-full min-w-0 items-center gap-3 rounded-md border border-gray-200/70 bg-white/60 px-3 h-9 shadow-sm dark:border-white/10 dark:bg-white/5'
          : 'w-full rounded-xl border border-gray-200/70 bg-white/70 px-3 py-2 shadow-sm dark:border-white/10 dark:bg-gray-900/60',
        className,
      ].join(' ')}
    >
      {compact ? (
        <>
          {label ? (
            <label
              htmlFor={inputId}
              className="shrink-0 text-sm font-medium leading-none text-gray-900 dark:text-gray-100"
            >
              {label}
            </label>
          ) : null}

          <div className="relative min-w-0 flex-1">
            <div className="pointer-events-none absolute inset-y-0 left-0 right-0">
              <div
                className="absolute left-0 right-0 rounded-full bg-gray-200/90 dark:bg-white/10"
                style={{
                  height: `${trackH}px`,
                  top: '50%',
                  transform: 'translateY(-50%)',
                }}
              />
              <div
                className="absolute left-0 rounded-full bg-indigo-500 dark:bg-indigo-400"
                style={{
                  width: `${percent}%`,
                  height: `${trackH}px`,
                  top: '50%',
                  transform: 'translateY(-50%)',
                }}
              />
            </div>

            <input
              id={inputId}
              type="range"
              min={min}
              max={max}
              step={step}
              value={clamped}
              disabled={disabled}
              aria-label={label ?? 'Slider'}
              aria-valuemin={min}
              aria-valuemax={max}
              aria-valuenow={clamped}
              className={[
                `
                relative z-10 block w-full cursor-pointer appearance-none bg-transparent
                disabled:cursor-not-allowed disabled:opacity-50
                focus:outline-none touch-pan-x

                [&::-webkit-slider-runnable-track]:bg-transparent
                [&::-webkit-slider-runnable-track]:appearance-none

                [&::-webkit-slider-thumb]:appearance-none
                [&::-webkit-slider-thumb]:rounded-full
                [&::-webkit-slider-thumb]:border
                [&::-webkit-slider-thumb]:border-white/80
                [&::-webkit-slider-thumb]:bg-indigo-500
                [&::-webkit-slider-thumb]:shadow-sm
                dark:[&::-webkit-slider-thumb]:border-gray-950
                dark:[&::-webkit-slider-thumb]:bg-indigo-400

                [&::-moz-range-track]:bg-transparent
                [&::-moz-range-track]:border-0

                [&::-moz-range-thumb]:rounded-full
                [&::-moz-range-thumb]:border
                [&::-moz-range-thumb]:border-white/80
                [&::-moz-range-thumb]:bg-indigo-500
                [&::-moz-range-thumb]:shadow-sm
                dark:[&::-moz-range-thumb]:border-gray-950
                dark:[&::-moz-range-thumb]:bg-indigo-400
                `,
                inputClassName,
              ].join(' ')}
              style={
                {
                  height: `${inputH}px`,
                  WebkitAppearance: 'none',
                  appearance: 'none',
                  ['--slider-track-h' as any]: `${trackH}px`,
                  ['--slider-thumb-size' as any]: `${thumbSize}px`,
                  ['--slider-thumb-offset' as any]: `${thumbOffset}px`,
                } as CSSProperties
              }
              onChange={(e) => handleChange(Number(e.target.value))}
              onPointerUp={handleCommit}
              onMouseUp={handleCommit}
              onTouchEnd={handleCommit}
              onKeyUp={(e) => {
                if (
                  e.key === 'ArrowLeft' ||
                  e.key === 'ArrowRight' ||
                  e.key === 'ArrowUp' ||
                  e.key === 'ArrowDown' ||
                  e.key === 'Home' ||
                  e.key === 'End' ||
                  e.key === 'PageUp' ||
                  e.key === 'PageDown'
                ) {
                  onChangeEnd?.(clamp(Number(e.currentTarget.value), min, max))
                }
              }}
            />

            <style>{`
              input[type='range']::-webkit-slider-runnable-track {
                height: var(--slider-track-h);
              }

              input[type='range']::-webkit-slider-thumb {
                width: var(--slider-thumb-size);
                height: var(--slider-thumb-size);
                margin-top: var(--slider-thumb-offset);
                -webkit-appearance: none;
              }

              input[type='range']::-moz-range-track {
                height: var(--slider-track-h);
              }

              input[type='range']::-moz-range-thumb {
                width: var(--slider-thumb-size);
                height: var(--slider-thumb-size);
                appearance: none;
              }
            `}</style>
          </div>

          {showValueLabel ? (
            <div className="shrink-0 text-xs font-medium tabular-nums text-gray-500 dark:text-gray-400">
              {resolvedValueLabel}
            </div>
          ) : null}

          {canReset ? (
            <button
              type="button"
              disabled={disabled}
              onClick={handleReset}
              className="
                inline-flex h-7 shrink-0 items-center rounded-md px-2 text-xs font-medium
                text-gray-700 ring-1 ring-gray-200 transition-colors
                hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50
                dark:text-gray-200 dark:ring-white/10 dark:hover:bg-white/10
              "
            >
              {resetLabel}
            </button>
          ) : null}
        </>
      ) : (
        <>
          {(label || hint || showValueLabel || canReset) ? (
            <div className="mb-2 flex items-start justify-between gap-3">
              {(label || hint) ? (
                <div className="min-w-0">
                  {label ? (
                    <label
                      htmlFor={inputId}
                      className="block text-sm font-medium text-gray-900 dark:text-gray-100"
                    >
                      {label}
                    </label>
                  ) : null}

                  {hint ? (
                    <div className="text-xs text-gray-600 dark:text-gray-300">
                      {hint}
                    </div>
                  ) : null}
                </div>
              ) : null}

              {(showValueLabel || canReset) ? (
                <div className="flex shrink-0 items-center gap-2">
                  {showValueLabel ? (
                    <div className="rounded-md bg-gray-100 px-2 py-1 text-xs font-medium tabular-nums text-gray-500 dark:bg-white/10 dark:text-gray-400">
                      {resolvedValueLabel}
                    </div>
                  ) : null}

                  {canReset ? (
                    <button
                      type="button"
                      disabled={disabled}
                      onClick={handleReset}
                      className="
                        inline-flex h-7 items-center rounded-md px-2 text-xs font-medium
                        text-gray-700 ring-1 ring-gray-200 transition-colors
                        hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50
                        dark:text-gray-200 dark:ring-white/10 dark:hover:bg-white/10
                      "
                    >
                      {resetLabel}
                    </button>
                  ) : null}
                </div>
              ) : null}
            </div>
          ) : null}

          <div className="relative min-w-0">
            <div className="pointer-events-none absolute inset-y-0 left-0 right-0">
              <div
                className="absolute left-0 right-0 rounded-full bg-gray-200 dark:bg-white/10"
                style={{
                  height: `${trackH}px`,
                  top: '50%',
                  transform: 'translateY(-50%)',
                }}
              />
              <div
                className="absolute left-0 rounded-full bg-indigo-500 dark:bg-indigo-400"
                style={{
                  width: `${percent}%`,
                  height: `${trackH}px`,
                  top: '50%',
                  transform: 'translateY(-50%)',
                }}
              />
            </div>

            <input
              id={inputId}
              type="range"
              min={min}
              max={max}
              step={step}
              value={clamped}
              disabled={disabled}
              aria-label={label ?? 'Slider'}
              aria-valuemin={min}
              aria-valuemax={max}
              aria-valuenow={clamped}
              className={[
                `
                relative z-10 block w-full cursor-pointer appearance-none bg-transparent
                disabled:cursor-not-allowed disabled:opacity-50
                focus:outline-none touch-pan-x

                [&::-webkit-slider-runnable-track]:bg-transparent
                [&::-webkit-slider-runnable-track]:appearance-none

                [&::-webkit-slider-thumb]:appearance-none
                [&::-webkit-slider-thumb]:rounded-full
                [&::-webkit-slider-thumb]:border
                [&::-webkit-slider-thumb]:border-white/80
                [&::-webkit-slider-thumb]:bg-indigo-500
                [&::-webkit-slider-thumb]:shadow-sm
                dark:[&::-webkit-slider-thumb]:border-gray-950
                dark:[&::-webkit-slider-thumb]:bg-indigo-400

                [&::-moz-range-track]:bg-transparent
                [&::-moz-range-track]:border-0

                [&::-moz-range-thumb]:rounded-full
                [&::-moz-range-thumb]:border
                [&::-moz-range-thumb]:border-white/80
                [&::-moz-range-thumb]:bg-indigo-500
                [&::-moz-range-thumb]:shadow-sm
                dark:[&::-moz-range-thumb]:border-gray-950
                dark:[&::-moz-range-thumb]:bg-indigo-400
                `,
                inputClassName,
              ].join(' ')}
              style={
                {
                  height: `${thumbSize}px`,
                  WebkitAppearance: 'none',
                  appearance: 'none',
                  ['--slider-track-h' as any]: `${trackH}px`,
                  ['--slider-thumb-size' as any]: `${thumbSize}px`,
                  ['--slider-thumb-offset' as any]: `${thumbOffset}px`,
                } as CSSProperties
              }
              onChange={(e) => handleChange(Number(e.target.value))}
              onPointerUp={handleCommit}
              onMouseUp={handleCommit}
              onTouchEnd={handleCommit}
              onKeyUp={(e) => {
                if (
                  e.key === 'ArrowLeft' ||
                  e.key === 'ArrowRight' ||
                  e.key === 'ArrowUp' ||
                  e.key === 'ArrowDown' ||
                  e.key === 'Home' ||
                  e.key === 'End' ||
                  e.key === 'PageUp' ||
                  e.key === 'PageDown'
                ) {
                  onChangeEnd?.(clamp(Number(e.currentTarget.value), min, max))
                }
              }}
            />

            <style>{`
              input[type='range']::-webkit-slider-runnable-track {
                height: var(--slider-track-h);
              }

              input[type='range']::-webkit-slider-thumb {
                width: var(--slider-thumb-size);
                height: var(--slider-thumb-size);
                margin-top: var(--slider-thumb-offset);
                -webkit-appearance: none;
              }

              input[type='range']::-moz-range-track {
                height: var(--slider-track-h);
              }

              input[type='range']::-moz-range-thumb {
                width: var(--slider-thumb-size);
                height: var(--slider-thumb-size);
                appearance: none;
              }
            `}</style>
          </div>

          {showMinMaxLabels ? (
            <div className="mt-1 flex items-center justify-between text-[11px] text-gray-500 dark:text-gray-400">
              <span>{resolvedMinLabel}</span>
              <span>{resolvedMaxLabel}</span>
            </div>
          ) : null}
        </>
      )}
    </div>
  )
}