<template>
  <div class="swipeable-cards-container">
    <!-- Cards Track -->
    <div
      class="cards-track"
      ref="trackRef"
      :style="trackStyle"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
    >
      <div
        v-for="(_, index) in totalCards"
        :key="index"
        class="card-slide"
        :class="{ active: index === currentIndex }"
      >
        <slot :name="`card-${index}`"></slot>
      </div>
    </div>

    <!-- Dots Indicator -->
    <div class="dots-indicator" v-if="showDots && totalCards > 1">
      <button
        v-for="index in totalCards"
        :key="index"
        class="dot"
        :class="{ active: index - 1 === currentIndex }"
        @click="goToCard(index - 1)"
        :aria-label="`Mergi la cardul ${index}`"
      />
    </div>
  </div>
</template>

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

/**
 * SwipeableCards - Touch swipeable carousel for mobile KPI cards
 *
 * Props:
 * - totalCards: Number of cards in the carousel
 * - showDots: Whether to show the dots indicator (default: true)
 * - autoPlay: Whether to auto-advance cards (default: false)
 * - autoPlayInterval: Interval in ms for auto-play (default: 5000)
 *
 * Events:
 * - update:currentIndex: Emitted when current card index changes
 *
 * Slots:
 * - card-0, card-1, card-2, etc.: Named slots for each card
 *
 * Features:
 * - Horizontal touch swipe (left/right)
 * - Smooth CSS transitions
 * - Dots indicator for position
 * - Visual feedback during drag
 * - Responsive touch thresholds
 */

const props = defineProps({
  /**
   * Total number of cards in the carousel
   */
  totalCards: {
    type: Number,
    required: true,
    validator: (value) => value > 0
  },
  /**
   * Whether to show the navigation dots
   */
  showDots: {
    type: Boolean,
    default: true
  },
  /**
   * Whether to auto-advance cards
   */
  autoPlay: {
    type: Boolean,
    default: false
  },
  /**
   * Auto-play interval in milliseconds
   */
  autoPlayInterval: {
    type: Number,
    default: 5000
  }
})

const emit = defineEmits(['update:currentIndex'])

// Refs
const trackRef = ref(null)
const currentIndex = ref(0)
const isDragging = ref(false)
const dragOffset = ref(0)

// Touch tracking state
let touchStartX = 0
let touchStartY = 0
let touchCurrentX = 0
let isSwiping = false
let autoPlayTimer = null

// Swipe thresholds
const SWIPE_THRESHOLD = 50 // Minimum swipe distance to change card
const SWIPE_VELOCITY_THRESHOLD = 0.3 // Minimum velocity for quick swipes
const ANGLE_THRESHOLD = 30 // Maximum angle (degrees) for horizontal swipe detection

/**
 * Calculate the track transform based on current index and drag offset
 */
const trackStyle = computed(() => {
  const translateX = -currentIndex.value * 100 + (dragOffset.value / getTrackWidth()) * 100
  return {
    transform: `translateX(${translateX}%)`,
    transition: isDragging.value ? 'none' : 'transform var(--transition-normal)'
  }
})

/**
 * Get track container width for calculations
 */
const getTrackWidth = () => {
  return trackRef.value?.clientWidth || window.innerWidth
}

/**
 * Navigate to a specific card index
 */
const goToCard = (index) => {
  if (index < 0 || index >= props.totalCards) return
  currentIndex.value = index
  emit('update:currentIndex', index)
}

/**
 * Navigate to the next card
 */
const nextCard = () => {
  if (currentIndex.value < props.totalCards - 1) {
    goToCard(currentIndex.value + 1)
  }
}

/**
 * Navigate to the previous card
 */
const prevCard = () => {
  if (currentIndex.value > 0) {
    goToCard(currentIndex.value - 1)
  }
}

/**
 * Handle touch start event
 */
const handleTouchStart = (event) => {
  // Record starting position
  touchStartX = event.touches[0].clientX
  touchStartY = event.touches[0].clientY
  touchCurrentX = touchStartX
  isSwiping = false

  // Stop auto-play during interaction
  stopAutoPlay()
}

/**
 * Handle touch move event
 */
const handleTouchMove = (event) => {
  if (!touchStartX) return

  touchCurrentX = event.touches[0].clientX
  const touchCurrentY = event.touches[0].clientY

  const deltaX = touchCurrentX - touchStartX
  const deltaY = touchCurrentY - touchStartY

  // Determine if this is a horizontal swipe
  // Check angle: if angle is too steep, it's a vertical scroll
  const angle = Math.abs(Math.atan2(deltaY, deltaX) * (180 / Math.PI))

  if (!isSwiping) {
    // First significant movement - determine direction
    if (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) {
      if (angle < ANGLE_THRESHOLD || angle > (180 - ANGLE_THRESHOLD)) {
        // Horizontal swipe
        isSwiping = true
        isDragging.value = true
      } else {
        // Vertical scroll - don't interfere
        return
      }
    }
  }

  if (isSwiping) {
    // Prevent vertical scroll while swiping horizontally
    event.preventDefault()

    // Apply resistance at boundaries
    let adjustedDelta = deltaX
    if (
      (currentIndex.value === 0 && deltaX > 0) ||
      (currentIndex.value === props.totalCards - 1 && deltaX < 0)
    ) {
      // Apply resistance (50% of movement)
      adjustedDelta = deltaX * 0.3
    }

    dragOffset.value = adjustedDelta
  }
}

/**
 * Handle touch end event
 */
const handleTouchEnd = (event) => {
  if (!isSwiping) {
    resetTouchState()
    return
  }

  const deltaX = touchCurrentX - touchStartX
  const trackWidth = getTrackWidth()
  const percentMoved = Math.abs(deltaX) / trackWidth

  // Calculate swipe velocity (for quick swipes)
  const touchDuration = event.timeStamp - (event.changedTouches[0]?.timeStamp || event.timeStamp)
  const velocity = Math.abs(deltaX) / (touchDuration || 1)

  // Determine if we should change cards
  const shouldChange =
    Math.abs(deltaX) > SWIPE_THRESHOLD ||
    (velocity > SWIPE_VELOCITY_THRESHOLD && percentMoved > 0.1)

  if (shouldChange) {
    if (deltaX > 0 && currentIndex.value > 0) {
      // Swiped right - go to previous
      prevCard()
    } else if (deltaX < 0 && currentIndex.value < props.totalCards - 1) {
      // Swiped left - go to next
      nextCard()
    }
  }

  // Reset state
  resetTouchState()

  // Restart auto-play after interaction
  if (props.autoPlay) {
    startAutoPlay()
  }
}

/**
 * Reset touch tracking state
 */
const resetTouchState = () => {
  touchStartX = 0
  touchStartY = 0
  touchCurrentX = 0
  isSwiping = false
  isDragging.value = false
  dragOffset.value = 0
}

/**
 * Start auto-play timer
 */
const startAutoPlay = () => {
  if (!props.autoPlay) return

  stopAutoPlay()
  autoPlayTimer = setInterval(() => {
    if (currentIndex.value < props.totalCards - 1) {
      nextCard()
    } else {
      goToCard(0) // Loop back to first
    }
  }, props.autoPlayInterval)
}

/**
 * Stop auto-play timer
 */
const stopAutoPlay = () => {
  if (autoPlayTimer) {
    clearInterval(autoPlayTimer)
    autoPlayTimer = null
  }
}

// Watch for totalCards changes to reset index if needed
watch(() => props.totalCards, (newTotal) => {
  if (currentIndex.value >= newTotal) {
    goToCard(newTotal - 1)
  }
})

// Lifecycle
onMounted(() => {
  if (props.autoPlay) {
    startAutoPlay()
  }
})

onUnmounted(() => {
  stopAutoPlay()
})

// Expose methods for parent component
defineExpose({
  goToCard,
  nextCard,
  prevCard,
  currentIndex
})
</script>

<style scoped>
/* ================================================
   SwipeableCards Component Styles
   Touch swipeable carousel for mobile KPI cards
   ================================================ */

.swipeable-cards-container {
  position: relative;
  width: 100%;
  overflow: hidden;
  /* Padding for dots indicator */
  padding-bottom: var(--space-xl);
}

/* Cards track - horizontal scrolling container */
.cards-track {
  display: flex;
  width: 100%;
  will-change: transform;
  /* Prevent text selection during swipe */
  user-select: none;
  -webkit-user-select: none;
  /* Smooth touch scrolling */
  touch-action: pan-y pinch-zoom;
}

/* Individual card slide */
.card-slide {
  flex: 0 0 100%;
  width: 100%;
  min-width: 0;
  padding: 0 var(--space-sm);
  box-sizing: border-box;
}

/* First and last card padding adjustments */
.card-slide:first-child {
  padding-left: var(--space-md);
}

.card-slide:last-child {
  padding-right: var(--space-md);
}

/* ================================================
   Dots Indicator
   ================================================ */

.dots-indicator {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) 0;
}

/* Individual dot */
.dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--surface-border);
  border: none;
  padding: 0;
  cursor: pointer;
  transition: all var(--transition-fast);
  /* Expand touch target */
  position: relative;
}

/* Expanded touch target (invisible) */
.dot::before {
  content: '';
  position: absolute;
  top: -8px;
  left: -8px;
  right: -8px;
  bottom: -8px;
}

/* Active dot */
.dot.active {
  width: 24px;
  background: var(--color-primary);
}

/* Hover state */
.dot:hover:not(.active) {
  background: var(--text-color-secondary);
}

/* Focus state for accessibility */
.dot:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-primary);
}

/* ================================================
   Dark Mode Support
   ================================================ */

/* Manual dark mode via data-theme attribute */
[data-theme="dark"] .dot {
  background: var(--surface-border);
}

[data-theme="dark"] .dot.active {
  background: var(--color-primary);
}

[data-theme="dark"] .dot:hover:not(.active) {
  background: var(--text-color-secondary);
}

/* Auto dark mode (when no manual theme is set) */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .dot {
    background: var(--surface-border);
  }

  :root:not([data-theme]) .dot.active {
    background: var(--color-primary);
  }

  :root:not([data-theme]) .dot:hover:not(.active) {
    background: var(--text-color-secondary);
  }
}
</style>
