'use client'
import { useState, useEffect, useRef, type CSSProperties, type ReactNode } from 'react'

type GeoData = Record<string, Record<string, string[]>>

interface CiudadSelectFieldProps {
  name: string
  label: ReactNode
  value: string
  required: boolean
  departamento?: string | null
  onChange: (value: string) => void
  error?: string
}

export function CiudadSelectField({
  name,
  label,
  value,
  required,
  departamento,
  onChange,
  error,
}: CiudadSelectFieldProps) {
  const [geoData, setGeoData] = useState<GeoData | null>(null)
  const [open, setOpen] = useState(false)
  const [activeIdx, setActiveIdx] = useState(-1)
  const [dropdownStyle, setDropdownStyle] = useState<CSSProperties>({})
  const inputRef = useRef<HTMLInputElement>(null)

  // Stable ref to always call the latest onChange without it in effect deps
  const onChangeRef = useRef(onChange)
  onChangeRef.current = onChange

  const prevDeptoRef = useRef(departamento)

  useEffect(() => {
    fetch('/data/geo_paraguay_full.json')
      .then((r) => r.json())
      .then(setGeoData)
      .catch(() => {})
  }, [])

  // Clear city when departamento changes so no orphan value remains
  useEffect(() => {
    if (prevDeptoRef.current !== departamento) {
      onChangeRef.current('')
      setOpen(false)
    }
    prevDeptoRef.current = departamento
  }, [departamento])

  // Close fixed dropdown on any scroll (input moves, list stays)
  useEffect(() => {
    if (!open) return
    const close = () => setOpen(false)
    window.addEventListener('scroll', close, { passive: true, capture: true })
    return () => window.removeEventListener('scroll', close, { capture: true })
  }, [open])

  function computeDropdownStyle() {
    if (!inputRef.current) return
    const rect = inputRef.current.getBoundingClientRect()
    setDropdownStyle({ top: rect.bottom + 4, left: rect.left, width: rect.width })
  }

  const ciudades: string[] = (() => {
    if (!geoData) return []
    if (departamento) return Object.keys(geoData[departamento] ?? {})
    return Object.values(geoData).flatMap((d) => Object.keys(d))
  })()

  const query = value.trim().toLowerCase()
  const suggestions =
    query.length >= 2
      ? ciudades.filter((c) => c.toLowerCase().includes(query)).slice(0, 10)
      : []

  function handleInput(v: string) {
    onChange(v)
    computeDropdownStyle()
    setOpen(true)
    setActiveIdx(-1)
  }

  function select(ciudad: string) {
    onChange(ciudad)
    setOpen(false)
    setActiveIdx(-1)
  }

  function handleKeyDown(e: React.KeyboardEvent) {
    if (!open || suggestions.length === 0) return
    if (e.key === 'ArrowDown') {
      e.preventDefault()
      setActiveIdx((i) => Math.min(i + 1, suggestions.length - 1))
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      setActiveIdx((i) => Math.max(i - 1, -1))
    } else if (e.key === 'Enter' && activeIdx >= 0) {
      e.preventDefault()
      select(suggestions[activeIdx])
    } else if (e.key === 'Escape') {
      setOpen(false)
    }
  }

  const listId = `${name}-suggestions`

  return (
    <div className="question-fieldset">
      <label className="question-legend" htmlFor={name}>
        {label}
        {required && <span className="required-mark" aria-hidden="true"> *</span>}
        {required && <span className="sr-only"> (obligatorio)</span>}
      </label>
      <div className="barrio-autocomplete-wrapper">
        <input
          type="text"
          id={name}
          name={name}
          value={value}
          required={required}
          aria-required={required}
          aria-describedby={error ? `${name}-error` : undefined}
          aria-invalid={!!error}
          aria-autocomplete="list"
          aria-controls={open && suggestions.length > 0 ? listId : undefined}
          aria-activedescendant={activeIdx >= 0 ? `${name}-opt-${activeIdx}` : undefined}
          autoComplete="off"
          className="text-short-input"
          ref={inputRef}
          onChange={(e) => handleInput(e.target.value)}
          onKeyDown={handleKeyDown}
          onFocus={() => { if (suggestions.length > 0) { computeDropdownStyle(); setOpen(true) } }}
          onBlur={() => setTimeout(() => setOpen(false), 150)}
        />
        {open && suggestions.length > 0 && (
          <ul
            id={listId}
            role="listbox"
            className="barrio-autocomplete-list"
            aria-label="Sugerencias de ciudades"
            style={dropdownStyle}
          >
            {suggestions.map((ciudad, i) => (
              <li
                key={ciudad}
                id={`${name}-opt-${i}`}
                role="option"
                aria-selected={i === activeIdx}
                className={`barrio-autocomplete-item${i === activeIdx ? ' barrio-autocomplete-item--active' : ''}`}
                onMouseDown={() => select(ciudad)}
                onTouchEnd={(e) => { e.preventDefault(); select(ciudad) }}
              >
                {ciudad}
              </li>
            ))}
          </ul>
        )}
      </div>
      {error && (
        <p role="alert" className="field-error" id={`${name}-error`}>
          {error}
        </p>
      )}
    </div>
  )
}
