import { useEffect, useMemo, useRef, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import {
  Facets,
  fetchFacets,
  fetchStores,
  formatInt,
  StoresResponse,
} from '../api'
import EmptyState from '../components/EmptyState'
import Skeleton from '../components/Skeleton'
import StoreCard from '../components/StoreCard'

export default function Stores() {
  const [searchParams, setSearchParams] = useSearchParams()
  const [facets, setFacets] = useState<Facets | null>(null)
  const [data, setData] = useState<StoresResponse | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(false)

  const region = searchParams.get('region') ?? ''
  const q = searchParams.get('q') ?? ''
  const withProducts = searchParams.get('avec_produits') !== '0'

  const [search, setSearch] = useState(q)
  const debounceRef = useRef<number | undefined>(undefined)

  useEffect(() => {
    setSearch(q)
  }, [q])

  useEffect(() => {
    const controller = new AbortController()
    fetchFacets(controller.signal)
      .then(setFacets)
      .catch(() => {})
    return () => controller.abort()
  }, [])

  useEffect(() => {
    const controller = new AbortController()
    setLoading(true)
    setError(false)
    fetchStores(
      {
        region: region || undefined,
        q: q || undefined,
        with_products: withProducts,
      },
      controller.signal
    )
      .then((res) => {
        setData(res)
        setLoading(false)
      })
      .catch((err: unknown) => {
        if (err instanceof DOMException && err.name === 'AbortError') return
        setError(true)
        setLoading(false)
      })
    return () => controller.abort()
  }, [region, q, withProducts])

  const update = useMemo(
    () =>
      (patch: { region?: string; q?: string; withProducts?: boolean }) => {
        setSearchParams(
          (prev) => {
            const next = new URLSearchParams(prev)
            const r = patch.region ?? region
            const query = patch.q ?? q
            const wp = patch.withProducts ?? withProducts
            if (r) next.set('region', r)
            else next.delete('region')
            if (query) next.set('q', query)
            else next.delete('q')
            if (!wp) next.set('avec_produits', '0')
            else next.delete('avec_produits')
            return next
          },
          { replace: true }
        )
      },
    [setSearchParams, region, q, withProducts]
  )

  function onSearchInput(value: string) {
    setSearch(value)
    window.clearTimeout(debounceRef.current)
    debounceRef.current = window.setTimeout(() => update({ q: value }), 300)
  }

  // Most stocked boutiques first.
  const sortedStores = useMemo(
    () =>
      [...(data?.items ?? [])].sort(
        (a, b) => b.product_count - a.product_count
      ),
    [data]
  )

  return (
    <div className="page stores">
      <div className="page-header">
        <h1>Boutiques</h1>
        {data && !loading && (
          <p className="catalog-count">
            {formatInt(data.total)} boutique{data.total === 1 ? '' : 's'}
          </p>
        )}
      </div>

      <div className="stores-toolbar">
        <input
          type="search"
          value={search}
          onChange={(e) => onSearchInput(e.target.value)}
          placeholder="Rechercher une boutique…"
          aria-label="Rechercher une boutique"
        />
        <select
          value={region}
          onChange={(e) => update({ region: e.target.value })}
          aria-label="Filtrer par région"
        >
          <option value="">Toutes les régions</option>
          {(facets?.all_regions ?? []).map((r) => (
            <option key={r} value={r}>
              {r}
            </option>
          ))}
        </select>
        <label className="toggle">
          <input
            type="checkbox"
            checked={withProducts}
            onChange={(e) => update({ withProducts: e.target.checked })}
          />
          <span>Avec produits</span>
        </label>
      </div>

      {loading ? (
        <div className="store-grid">
          {Array.from({ length: 8 }, (_, i) => (
            <div className="card store-card" key={i}>
              <div className="store-card-top">
                <Skeleton height="44px" width="44px" radius="50%" />
                <div className="store-card-heading">
                  <Skeleton height="1.3rem" width="70%" />
                </div>
              </div>
              <Skeleton height="0.9rem" width="50%" />
              <Skeleton height="0.9rem" width="60%" />
            </div>
          ))}
        </div>
      ) : error ? (
        <EmptyState
          variant="error"
          message="Impossible de charger les boutiques. Réessayez plus tard."
        />
      ) : sortedStores.length === 0 ? (
        <EmptyState message="Aucune boutique trouvée">
          <button
            type="button"
            className="btn btn-secondary"
            onClick={() => setSearchParams(new URLSearchParams(), { replace: true })}
          >
            Réinitialiser les filtres
          </button>
        </EmptyState>
      ) : (
        <div className="store-grid">
          {sortedStores.map((s) => (
            <StoreCard key={s.id} store={s} />
          ))}
        </div>
      )}
    </div>
  )
}
