import { useEffect, useRef, useState } from 'react'
import { Facets, formatInt, ORIGIN_KEYS, ORIGIN_LABELS } from '../api'

export interface FilterValues {
  q: string
  category: string
  region: string
  origins: string[]
  priceMin: string
  priceMax: string
  sort: string
}

interface BodyProps {
  facets: Facets | null
  values: FilterValues
  onChange: (patch: Partial<FilterValues>) => void
  /** Prefix for input ids so desktop + sheet instances don't collide. */
  idPrefix?: string
}

interface Props extends BodyProps {
  onReset: () => void
}

const SORT_OPTIONS: { value: string; label: string }[] = [
  { value: 'recent', label: 'Plus récents' },
  { value: 'price_asc', label: 'Prix croissant' },
  { value: 'price_desc', label: 'Prix décroissant' },
  { value: 'title', label: 'Titre (A–Z)' },
]

export function countActiveFilters(values: FilterValues): number {
  return (
    (values.q ? 1 : 0) +
    (values.category ? 1 : 0) +
    (values.region ? 1 : 0) +
    values.origins.length +
    (values.priceMin ? 1 : 0) +
    (values.priceMax ? 1 : 0)
  )
}

/**
 * The filter controls themselves — rendered inside the desktop sidebar
 * and inside the mobile bottom sheet.
 */
export function FiltersBody({ facets, values, onChange, idPrefix = '' }: BodyProps) {
  const [search, setSearch] = useState(values.q)
  const debounceRef = useRef<number | undefined>(undefined)
  const firstRender = useRef(true)

  // Keep local search in sync when URL changes externally (back button, chips…)
  useEffect(() => {
    setSearch(values.q)
  }, [values.q])

  // Debounced propagation of the search input (300 ms)
  useEffect(() => {
    if (firstRender.current) {
      firstRender.current = false
      return
    }
    window.clearTimeout(debounceRef.current)
    debounceRef.current = window.setTimeout(() => {
      if (search !== values.q) onChange({ q: search })
    }, 300)
    return () => window.clearTimeout(debounceRef.current)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [search])

  function toggleOrigin(key: string) {
    const next = values.origins.includes(key)
      ? values.origins.filter((o) => o !== key)
      : [...values.origins, key]
    onChange({ origins: next })
  }

  return (
    <div className="filters-body">
      <div className="filter-group">
        <label className="filter-label" htmlFor={`${idPrefix}filter-search`}>
          Recherche
        </label>
        <input
          id={`${idPrefix}filter-search`}
          type="search"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Mot-clé…"
        />
      </div>

      <div className="filter-group">
        <span className="filter-label">Catégories</span>
        <ul className="filter-category-list">
          <li>
            <button
              type="button"
              className={values.category === '' ? 'active' : ''}
              onClick={() => onChange({ category: '' })}
            >
              Toutes
            </button>
          </li>
          {(facets?.categories ?? []).map((c) => (
            <li key={c.key}>
              <button
                type="button"
                className={values.category === c.key ? 'active' : ''}
                onClick={() =>
                  onChange({
                    category: values.category === c.key ? '' : c.key,
                  })
                }
              >
                <span>{c.label}</span>
                <span className="filter-count">{formatInt(c.n)}</span>
              </button>
            </li>
          ))}
        </ul>
      </div>

      <div className="filter-group">
        <label className="filter-label" htmlFor={`${idPrefix}filter-region`}>
          Région
        </label>
        <select
          id={`${idPrefix}filter-region`}
          value={values.region}
          onChange={(e) => onChange({ region: e.target.value })}
        >
          <option value="">Toutes les régions</option>
          {(facets?.all_regions ?? []).map((r) => (
            <option key={r} value={r}>
              {r}
            </option>
          ))}
        </select>
      </div>

      <div className="filter-group">
        <span className="filter-label">Origine</span>
        {ORIGIN_KEYS.map((key) => (
          <label className="filter-checkbox" key={key}>
            <input
              type="checkbox"
              checked={values.origins.includes(key)}
              onChange={() => toggleOrigin(key)}
            />
            <span className={`origin-badge origin-${key}`}>
              <span className="origin-badge-letter">{key}</span>
            </span>
            <span>{ORIGIN_LABELS[key]}</span>
          </label>
        ))}
      </div>

      <div className="filter-group">
        <span className="filter-label">Prix</span>
        <div className="filter-price-row">
          <input
            type="number"
            min="0"
            inputMode="decimal"
            placeholder="Min"
            aria-label="Prix minimum"
            value={values.priceMin}
            onChange={(e) => onChange({ priceMin: e.target.value })}
          />
          <span aria-hidden="true">–</span>
          <input
            type="number"
            min="0"
            inputMode="decimal"
            placeholder="Max"
            aria-label="Prix maximum"
            value={values.priceMax}
            onChange={(e) => onChange({ priceMax: e.target.value })}
          />
        </div>
      </div>

      <div className="filter-group">
        <label className="filter-label" htmlFor={`${idPrefix}filter-sort`}>
          Trier par
        </label>
        <select
          id={`${idPrefix}filter-sort`}
          value={values.sort || 'recent'}
          onChange={(e) => onChange({ sort: e.target.value })}
        >
          {SORT_OPTIONS.map((o) => (
            <option key={o.value} value={o.value}>
              {o.label}
            </option>
          ))}
        </select>
      </div>
    </div>
  )
}

/**
 * Desktop sidebar (hidden on mobile — the bottom sheet takes over there).
 */
export default function Filters({ facets, values, onChange, onReset }: Props) {
  const activeCount = countActiveFilters(values)
  return (
    <aside className="filters" aria-label="Filtres">
      <div className="filters-title-row">
        <span className="filters-title">Filtres</span>
        {activeCount > 0 && (
          <button type="button" className="filters-reset-link" onClick={onReset}>
            Réinitialiser ({activeCount})
          </button>
        )}
      </div>
      <FiltersBody
        facets={facets}
        values={values}
        onChange={onChange}
        idPrefix="side-"
      />
    </aside>
  )
}
