<!-- app/components/HorizontalCards.vue -->
<!-- Faire défiler des cartes qui se déplacent horizontalement -->
<!-- Les cartes sont dans le composant qui appelle celui-çi, donc cela vaut pour tous types de cartes-->
<template>
  <!-- Root: classe is-scrolled pour piloter fade + hint -->
    <div
      class="hc"
      :class="[
        rootClass,
        { 'is-scrolled': hasScrolled }
      ]"
    >
      <!-- Optional title slot -->
      <div v-if="$slots.title" class="hc__header">
        <slot name="title" />
      </div>

      <!-- Hint icon (micro affordance) -->
      <button
        v-if="showHint"
        type="button"
        class="hc__hint"
        aria-label="Défiler vers la droite"
        @click="scrollByHint(1)"
      >
        <span class="hc__hint-icon">{{ hintIcon }}</span>
      </button>
      <button
        v-if="showHint"
        type="button"
        class="hc__hint--left"
        aria-label="Défiler vers la gauche"
        @click="scrollByHint(-1)"
      >
        <span class="hc__hint-icon">{{ hintIcon }}</span>
      </button>

      <!-- Scroller -->
      <div
        ref="scroller"
        class="hc__scroller"
        :class="scrollerClass"
        tabindex="0"
        role="region"
        :aria-label="ariaLabel"
        @scroll.passive="onScroll"
      >
        <div class="hc__track" :class="trackClass">
          <!-- Cards -->
          <slot />
        </div>
      </div>
    </div>
</template>

<script setup>
    import { onMounted, onBeforeUnmount, ref, computed, watch, nextTick } from 'vue'

    const props = defineProps({
      ariaLabel: { type: String, default: 'Horizontal content' },

      /** Active l’animation "nudge" une seule fois (localStorage) */
      nudgeOnce: { type: Boolean, default: true },
      hintKey: { type: String, default: 'horizontal-cards-hint-seen' },

      /** Nudge settings */
      nudgePx: { type: Number, default: 48 },
      nudgeDelayMs: { type: Number, default: 350 },
      nudgeReturnDelayMs: { type: Number, default: 450 },

      /** UI affordances */
      showHint: { type: Boolean, default: true },
      hintIcon: { type: String, default: '⇆' },

      /** Peek: % de padding-right du scroller pour montrer la carte suivante */
      peek: { type: Number, default: 30 }, // 25–40 conseillé

      /** Fade (px) : largeur du dégradé */
      fadeWidth: { type: Number, default: 64 },

      /** Classes hooks */
      rootClass: { type: [String, Array, Object], default: '' },
      scrollerClass: { type: [String, Array, Object], default: '' },
      trackClass: { type: [String, Array, Object], default: '' },

      // Reset scroll (ex: changement de filtre)
      resetKey: { type: [String, Number], default: null },
      resetBehavior: { type: String, default: 'smooth' }, // 'smooth' ou 'auto'
      resetDelayMs: { type: Number, default: 0 },
    })

    const scroller = ref(null)
    const hasScrolled = ref(false)

    let t = null

    const cssVars = computed(() => ({
      '--hc-peek': `${props.peek}%`,
      '--hc-fade-w': `${props.fadeWidth}px`
    }))

    const markSeen = () => {
      try { localStorage.setItem(props.hintKey, '1') } catch (_) {}
    }
    const isSeen = () => {
      try { return localStorage.getItem(props.hintKey) === '1' } catch (_) { return true }
    }

    const onScroll = () => {
      if (!hasScrolled.value) {
        hasScrolled.value = true
        markSeen()
      }
      if (t) clearTimeout(t)
      t = setTimeout(() => {}, 80)
    }

    const scrollByHint = (direction) => {
      const el = scroller.value
      if (!el) return

      const distance = Math.max(140, Math.round(el.clientWidth * 0.8))
      el.scrollBy({ left: distance * direction, behavior: 'smooth' })
    }

    onMounted(() => {
      const el = scroller.value
      if (!el) return

      // Inject vars on root element
      // (Vue n’aime pas style binding + class binding sur le root via computed uniquement,
      //  donc on set ici pour être sûr)
      el.closest('.hc')?.style?.setProperty('--hc-peek', `${props.peek}%`)
      el.closest('.hc')?.style?.setProperty('--hc-fade-w', `${props.fadeWidth}px`)

      if (!props.nudgeOnce) return
      if (isSeen()) return

      const reduce = window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches
      if (reduce) return

      const canScroll = el.scrollWidth > el.clientWidth + 4
      if (!canScroll) return

      setTimeout(() => {
        el.scrollBy({ left: props.nudgePx, behavior: 'smooth' })
        setTimeout(() => {
          el.scrollBy({ left: -props.nudgePx, behavior: 'smooth' })
          markSeen()
        }, props.nudgeReturnDelayMs)
      }, props.nudgeDelayMs)
    })

    onBeforeUnmount(() => {
      if (t) clearTimeout(t)
    })

    // Pour revenir à la première carte sur changement de filtre
    const resetToStart = async () => {
      const el = scroller.value
      if (!el) return

      await nextTick()

      // Important : si tu changes le contenu + transition, un petit délai peut aider
      const run = () => el.scrollTo({ left: 0, behavior: props.resetBehavior })

      if (props.resetDelayMs > 0) {
        setTimeout(run, props.resetDelayMs)
      } else {
        run()
      }
    }

    watch(
      () => props.resetKey,
      (nv, ov) => {
        // si c’est la première fois (ov === null) tu peux choisir de reset ou pas
        if (nv === ov) return
        resetToStart()
      }
    )
</script>

<style lang="scss">
    /* ==========================================================================
      HorizontalCards (no lib)
      - scroll-snap
      - peek (last card cut)
      - fade right
      - hint icon
      - nudge once (JS minimal)
      ========================================================================== */

    .hc {
      position: relative;

      /* Vars (fallbacks) */
      --hc-peek: 30%;
      --hc-fade-w: 64px;
    }

    /* Title slot */
    .hc__header {
      margin-bottom: 0.75rem;
    }

    /* Hint icon */
    .hc__hint {
      pointer-events: auto;
      border: 0;
      padding: 0;
      cursor: pointer;
      appearance: none;
      position: absolute;
      right: 10px;
      top: 50%;
      transform: translateY(-50%);
      display: grid;
      place-items: center;
      width: 34px;
      height: 34px;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.9);
      box-shadow: 0 6px 18px rgba(0,0,0,0.12);
      opacity: 1;
      transition: opacity 180ms ease, transform 180ms ease;
      z-index: 2;
    }
    .hc__hint--left {
      pointer-events: auto;
      border: 0;
      padding: 0;
      cursor: pointer;
      appearance: none;
      position: absolute;
      left: 10px;
      top: 50%;
      transform: translateY(-50%);
      display: grid;
      place-items: center;
      width: 34px;
      height: 34px;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.9);
      box-shadow: 0 6px 18px rgba(0,0,0,0.12);
      opacity: 1;
      transition: opacity 180ms ease, transform 180ms ease;
      z-index: 2;
    }

    .hc__hint-icon {
      font-size: 18px;
      line-height: 1;
    }

    /* Scroller */
    .hc__scroller {
      overflow-x: auto;
      overflow-y: hidden;
      -webkit-overflow-scrolling: touch;
      scroll-snap-type: x mandatory;

      // Cacher la barre de défilement horizontal
      /* Firefox */
      scrollbar-width: none;
      /* IE / Edge legacy */
      -ms-overflow-style: none;
      /* WebKit (Chrome, Safari, Edge Chromium) */
      &::-webkit-scrollbar {
        display: none;
      }

      /* ✅ peek */
      padding: 0.25rem var(--hc-peek) 0.25rem 0;
      outline: none;

      /* Fade right */
      &::after {
        content: '';
        pointer-events: none;
        position: absolute;
        top: 0;
        right: 0;
        width: var(--hc-fade-w);
        height: 100%;

        background: linear-gradient(
          to left,
          rgb(172 207 207 / 59%),
          rgba(172, 207, 207, 0)
        );
        opacity: 1;
        transition: opacity 180ms ease;
        z-index: 1;
      }

      &:focus-visible {
        outline: 2px solid currentColor;
        outline-offset: 6px;
      }
    }

    /* Track */
    .hc__track {
      display: flex;
      flex-wrap: nowrap;
      gap: 20px;
      align-items: stretch;
    }

    /* Snap + “rail-friendly” defaults for children */
    .hc__track > * {
      flex: 0 0 auto;
      scroll-snap-align: start;
    }



    /* After first scroll: calm UI */
    .hc.is-scrolled {
      .hc__hint, .hc__hint--left {
        background: rgba(172, 207, 207, 0.9);
        //opacity: 0;
        transform: translateY(-50%) scale(0.96);
      }
      .hc__scroller::after {
        opacity: 0.55;
      }
    }
</style>
