"use client"

import { useState, useRef, useEffect, useCallback, useMemo } from "react"
import Image from "next/image"
import Link from "next/link"
import { Badge } from "@/components/ui/badge"
import { formatPrice } from "@/lib/utils"
import { productImage, materialImage } from "@/lib/product-image"
import type { Facet } from "@/lib/facets"

export interface ShopProduct {
  id: string
  name: string
  slug: string
  price: number
  images: string[]
  stock: number
  styles: string[]
  materials: string[]
  category: string
  drop: { name: string; status: "UPCOMING" | "LIVE" | "SOLD_OUT" } | null
}

type Combo = { style: string; material: string; category: string }
type FacetKey = keyof Combo

const rand = (n: number) => Math.floor(Math.random() * n)
const LONG_PRESS_MS = 450 // appui/clic long avant l'ouverture de la molette
const MOVE_CANCEL_PX = 14 // au-delà, le geste est un swipe (annule l'appui long)
const STEP_PX = 30 // pixels de drag vertical par valeur

function matchCombo(p: ShopProduct, c: Combo): boolean {
  return p.styles.includes(c.style) && p.materials.includes(c.material) && p.category === c.category
}

/**
 * Expérience shop unique (souris et tactile) : 3 sélecteurs de catégorie
 * + carrousel vedette plein écran. Identique sur desktop et mobile.
 */
export function ShopExperience({
  products,
  styles,
  materials,
  categories,
}: {
  products: ShopProduct[]
  styles: Facet[]
  materials: Facet[]
  categories: Facet[]
}) {
  const N = products.length

  const facetsOf = useCallback(
    (p: ShopProduct): Combo => ({
      style: p.styles[0] ?? "",
      material: p.materials[0] ?? "",
      category: p.category,
    }),
    []
  )
  const materialLabel = useMemo(
    () => Object.fromEntries(materials.map((f) => [f.slug, f.label])),
    [materials]
  )

  const [combo, setCombo] = useState<Combo>(() =>
    products[0] ? { style: products[0].styles[0], material: products[0].materials[0], category: products[0].category } : { style: "", material: "", category: "" }
  )
  const [feat, setFeat] = useState(0)
  const [auto, setAuto] = useState(true)
  const resumeTimer = useRef<ReturnType<typeof setTimeout> | null>(null)

  const base = useMemo(() => products.filter((p) => matchCombo(p, combo)), [products, combo])

  const cur = base.length ? base[feat % base.length] : null

  const pause = useCallback(() => {
    setAuto(false)
    if (resumeTimer.current) clearTimeout(resumeTimer.current)
    resumeTimer.current = setTimeout(() => setAuto(true), 20000)
  }, [])

  // Auto-swap : article aléatoire (les catégories reflètent l'article)
  useEffect(() => {
    if (!auto || N === 0) return
    const id = setInterval(() => {
      setCombo(facetsOf(products[rand(N)]))
      setFeat(0)
    }, 2500)
    return () => clearInterval(id)
  }, [auto, N, products, facetsOf])

  useEffect(() => () => { if (resumeTimer.current) clearTimeout(resumeTimer.current) }, [])

  // Swipe IMAGE : article suivant dans la sélection ; si ≤1, élargit à tout
  const moveArticle = useCallback(
    (dir: 1 | -1) => {
      pause()
      if (base.length > 1) {
        setFeat((f) => (f + dir + base.length) % base.length)
        return
      }
      const anchor = base[0]
      const idxAll = anchor ? products.findIndex((p) => p.id === anchor.id) : 0
      const nxt = products[((idxAll + dir) % N + N) % N]
      setCombo(facetsOf(nxt))
      setFeat(0)
    },
    [pause, products, N, facetsOf, base]
  )

  // Swipe catégorie : avance d'UNE valeur dans TOUT le vocabulaire (toutes
  // les catégories sont accessibles, même sans produit)
  const cycleFacet = useCallback(
    (facet: FacetKey, values: Facet[], dir: 1 | -1) => {
      pause()
      setCombo((prev) => {
        const n = values.length
        let idx = values.findIndex((v) => v.slug === prev[facet])
        if (idx < 0) idx = 0
        return { ...prev, [facet]: values[((idx + dir) % n + n) % n].slug }
      })
      setFeat(0)
    },
    [pause]
  )

  // Molette (appui/clic long) : choisit n'importe quelle valeur
  const selectFacet = useCallback(
    (facet: FacetKey, slug: string) => {
      pause()
      setCombo((prev) => ({ ...prev, [facet]: slug }))
      setFeat(0)
    },
    [pause]
  )

  if (N === 0) return null

  const query = cur?.styles[0] ? `?style=${cur.styles[0]}` : ""

  return (
    <div
      className="relative flex flex-col md:flex-row md:items-stretch gap-0 md:gap-10 h-[calc(100svh-7.5rem)] w-full"
      onPointerDown={pause}
    >
      {/* Colonne gauche : 3 catégories. swipe = change cette catégorie · appui/clic long = molette */}
      <div className="shrink-0 flex flex-col justify-center gap-3 pt-3 md:pt-0 md:w-72 lg:w-80">
        <CategoryControl
          values={styles}
          currentSlug={combo.style}
          onSwipe={(dir) => cycleFacet("style", styles, dir)}
          onSelect={(slug) => selectFacet("style", slug)}
        />
        <CategoryControl
          values={materials}
          currentSlug={combo.material}
          onSwipe={(dir) => cycleFacet("material", materials, dir)}
          onSelect={(slug) => selectFacet("material", slug)}
        />
        <CategoryControl
          values={categories}
          currentSlug={combo.category}
          onSwipe={(dir) => cycleFacet("category", categories, dir)}
          onSelect={(slug) => selectFacet("category", slug)}
        />
      </div>

      {/* Colonne droite : image. Produits de la sélection, ou vignette matériau si aucun */}
      <div className="flex-1 min-h-0 mt-3 md:mt-0">
        {base.length ? (
          <FeaturedSlider products={base} index={feat % base.length} onAdvance={moveArticle} query={query} />
        ) : (
          <MaterialTeaser
            img={materialImage(combo.material)}
            label={materialLabel[combo.material] ?? combo.material}
            onAdvance={moveArticle}
          />
        )}
      </div>
    </div>
  )
}

/* ─── Vignette matériau (aucun produit pour la combinaison) ────────────────── */
function MaterialTeaser({
  img,
  label,
  onAdvance,
}: {
  img: string | null
  label: string
  onAdvance: (dir: 1 | -1) => void
}) {
  const startX = useRef<number | null>(null)
  function onDown(e: React.PointerEvent) {
    startX.current = e.clientX
  }
  function onUp(e: React.PointerEvent) {
    if (startX.current === null) return
    const dx = e.clientX - startX.current
    if (Math.abs(dx) > 40) onAdvance(dx < 0 ? 1 : -1)
    startX.current = null
  }
  return (
    <div
      className="relative h-full overflow-hidden bg-[var(--surface)] cursor-grab active:cursor-grabbing"
      onPointerDown={onDown}
      onPointerUp={onUp}
    >
      {img && (
        <Image src={img} alt={label} fill sizes="(max-width: 768px) 100vw, 28rem" className="object-cover opacity-40" draggable={false} />
      )}
      <div className="absolute inset-0 flex flex-col items-center justify-center gap-2 bg-gradient-to-t from-[var(--bg)] via-transparent to-transparent">
        <span className="font-mono text-[10px] uppercase tracking-widest text-[var(--text-muted)]">
          Aucun produit
        </span>
        <span className="font-heading text-2xl font-bold uppercase tracking-tight text-[var(--text)]">
          {label}
        </span>
        <span className="font-mono text-[10px] uppercase tracking-widest text-[var(--accent)]">
          Bientôt
        </span>
      </div>
    </div>
  )
}

/* ─── Catégorie : swipe = article · appui/clic long → molette verticale ────── */
// Exporté : réutilisé tel quel par la page /drops pour filtrer les drops.
export function CategoryControl({
  values,
  currentSlug,
  onSwipe,
  onSelect,
}: {
  values: Facet[]
  currentSlug: string
  onSwipe: (dir: 1 | -1) => void
  onSelect: (slug: string) => void
}) {
  const n = values.length
  const curIdx = Math.max(0, values.findIndex((v) => v.slug === currentSlug))
  const prevV = values[(curIdx - 1 + n) % n]
  const curV = values[curIdx]
  const nextV = values[(curIdx + 1) % n]

  const [open, setOpen] = useState(false)
  const [highlight, setHighlight] = useState(0)

  const startX = useRef(0)
  const startY = useRef(0)
  const openY = useRef(0)
  const baseHi = useRef(0)
  const hiRef = useRef(0)
  const openedRef = useRef(false)
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null)

  const setHi = (h: number) => {
    hiRef.current = h
    setHighlight(h)
  }

  function onDown(e: React.PointerEvent) {
    e.currentTarget.setPointerCapture(e.pointerId)
    startX.current = e.clientX
    startY.current = e.clientY
    openedRef.current = false
    if (timer.current) clearTimeout(timer.current)
    timer.current = setTimeout(() => {
      openedRef.current = true
      openY.current = startY.current
      baseHi.current = curIdx
      setHi(curIdx)
      setOpen(true)
    }, LONG_PRESS_MS)
  }

  function onMove(e: React.PointerEvent) {
    if (!openedRef.current) {
      if (
        Math.abs(e.clientX - startX.current) > MOVE_CANCEL_PX ||
        Math.abs(e.clientY - startY.current) > MOVE_CANCEL_PX
      ) {
        if (timer.current) clearTimeout(timer.current)
      }
    } else {
      const dy = e.clientY - openY.current
      const steps = Math.round(dy / STEP_PX)
      setHi(((baseHi.current + steps) % n + n) % n)
    }
  }

  function onUp(e: React.PointerEvent) {
    if (timer.current) clearTimeout(timer.current)
    if (openedRef.current) {
      openedRef.current = false
      setOpen(false)
      onSelect(values[hiRef.current].slug)
    } else {
      const dx = e.clientX - startX.current
      if (Math.abs(dx) > 35) onSwipe(dx < 0 ? 1 : -1)
    }
  }

  return (
    <div className="relative">
      <div
        onPointerDown={onDown}
        onPointerMove={onMove}
        onPointerUp={onUp}
        onPointerCancel={onUp}
        className="relative flex items-center justify-center overflow-hidden select-none touch-none h-10 cursor-pointer [-webkit-touch-callout:none]"
      >
        {/* Voisine gauche (estompée) */}
        <span className="absolute left-1 max-w-[26%] truncate font-mono text-xs font-bold uppercase tracking-wider text-[var(--accent)] opacity-25 text-left">
          {prevV.label}
        </span>
        {/* Catégorie sélectionnée (centre) — remontée à chaque changement pour rejouer le fondu */}
        <span
          key={curV.slug}
          className="facet-value max-w-[46%] truncate font-mono text-xl font-bold uppercase tracking-wider text-[var(--accent)]"
        >
          {curV.label}
        </span>
        {/* Voisine droite (estompée) */}
        <span className="absolute right-1 max-w-[26%] truncate font-mono text-xs font-bold uppercase tracking-wider text-[var(--accent)] opacity-25 text-right">
          {nextV.label}
        </span>
      </div>

      {/* Molette verticale (appui/clic long) — opacité haut/bas */}
      {open && (
        <div className="absolute left-0 right-0 top-0 z-50 bg-[var(--bg)]/95 backdrop-blur-sm py-6 pointer-events-none">
          <div className="flex flex-col items-center gap-1">
            {[-2, -1, 0, 1, 2].map((off) => {
              const v = values[((highlight + off) % n + n) % n]
              const center = off === 0
              return (
                <span
                  key={off}
                  className={`font-mono uppercase tracking-wider truncate px-3 transition-all ${
                    center
                      ? "text-xl font-bold text-[var(--accent)]"
                      : Math.abs(off) === 1
                      ? "text-sm text-[var(--text-secondary)] opacity-70"
                      : "text-xs text-[var(--text-muted)] opacity-40"
                  }`}
                >
                  {v.label}
                </span>
              )
            })}
          </div>
        </div>
      )}
    </div>
  )
}

/* ─── Carrousel vedette pleine hauteur, animation de glissement ────────────── */
function FeaturedSlider({
  products,
  index,
  onAdvance,
  query,
}: {
  products: ShopProduct[]
  index: number
  onAdvance: (dir: 1 | -1) => void
  query: string
}) {
  const startX = useRef<number | null>(null)
  const swiped = useRef(false)
  const [drag, setDrag] = useState(0)
  const dragging = useRef(false)

  function onDown(e: React.PointerEvent) {
    e.currentTarget.setPointerCapture(e.pointerId)
    startX.current = e.clientX
    swiped.current = false
    dragging.current = true
  }
  function onMove(e: React.PointerEvent) {
    if (!dragging.current || startX.current === null) return
    setDrag(e.clientX - startX.current)
  }
  function onUp(e: React.PointerEvent) {
    if (startX.current === null) return
    const dx = e.clientX - startX.current
    dragging.current = false
    setDrag(0)
    if (Math.abs(dx) > 40) {
      swiped.current = true
      onAdvance(dx < 0 ? 1 : -1)
    }
    startX.current = null
  }

  return (
    <div
      className="relative h-full overflow-hidden cursor-grab active:cursor-grabbing"
      onPointerDown={onDown}
      onPointerMove={onMove}
      onPointerUp={onUp}
      onPointerCancel={onUp}
    >
      <div
        className={`flex h-full ${drag !== 0 ? "" : "transition-transform duration-300 ease-out"}`}
        style={{ transform: `translateX(calc(${-index * 100}% + ${drag}px))` }}
      >
        {products.map((p) => {
          const isSoldOut = p.stock === 0 || p.drop?.status === "SOLD_OUT"
          const img = productImage(p.images, p.materials)
          return (
            <Link
              key={p.id}
              href={`/shop/${p.slug}${query}`}
              onClick={(e) => {
                if (swiped.current) e.preventDefault()
              }}
              className="relative block w-full h-full shrink-0 bg-[var(--surface)]"
              aria-label={p.name}
            >
              {img ? (
                <Image
                  src={img}
                  alt={p.name}
                  fill
                  sizes="(max-width: 768px) 100vw, 28rem"
                  className={`object-cover ${isSoldOut ? "opacity-60 grayscale" : ""}`}
                  draggable={false}
                />
              ) : (
                <div className="absolute inset-0 flex items-center justify-center">
                  <span className="font-mono text-xs uppercase tracking-widest text-[var(--text-muted)]">
                    VALABEL
                  </span>
                </div>
              )}
              <div className="absolute top-4 left-4 flex flex-col gap-1.5">
                {p.drop?.status === "LIVE" && <Badge variant="drop">Drop Live</Badge>}
                {isSoldOut && <Badge variant="sold">Sold Out</Badge>}
              </div>
              <div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-[var(--bg)] to-transparent p-5 pt-16">
                <h3 className="font-heading text-lg font-semibold uppercase tracking-wide text-[var(--text)]">
                  {p.name}
                </h3>
                <p className="font-mono text-sm text-[var(--text-secondary)] mt-1">
                  {formatPrice(p.price)}
                </p>
              </div>
            </Link>
          )
        })}
      </div>
    </div>
  )
}
