<template>
  <Teleport to="body">
    <!-- Backdrop (only visible when expanded) -->
    <Transition name="fade">
      <div
        v-if="isOpen && !isMinimized"
        class="bottom-sheet-backdrop"
        @click="minimize"
      />
    </Transition>

    <!-- Bottom Sheet Container -->
    <Transition name="slide">
      <div
        v-if="isOpen"
        ref="sheetRef"
        class="bottom-sheet-container"
        :class="{ 'is-minimized': isMinimized }"
        :style="sheetStyle"
        @touchstart="onTouchStart"
        @touchmove="onTouchMove"
        @touchend="onTouchEnd"
      >
        <!-- Drag Handle -->
        <div class="drag-handle" @click="toggleMinimize">
          <div class="drag-indicator" />
          <span v-if="isMinimized" class="minimize-label">{{ title }} - Tap to expand</span>
        </div>

        <!-- Sheet Content -->
        <div v-show="!isMinimized" class="sheet-content">
          <slot />
        </div>
      </div>
    </Transition>

    <!-- Floating Restore Button (shown when minimized) -->
    <Transition name="pop">
      <button
        v-if="isOpen && isMinimized && showFloatingButton"
        class="floating-restore-button"
        @click="expand"
      >
        <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
        </svg>
        <span class="button-label">{{ title }}</span>
      </button>
    </Transition>
  </Teleport>
</template>

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

interface Props {
  isOpen: boolean
  title?: string
  showFloatingButton?: boolean
  minimizeThreshold?: number
  startMinimized?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  title: 'Panel',
  showFloatingButton: true,
  minimizeThreshold: 100,
  startMinimized: false,
})

const emit = defineEmits<{
  close: []
  minimize: []
  expand: []
}>()

// State
const sheetRef = ref<HTMLElement | null>(null)
const isMinimized = ref(props.startMinimized)
const touchStartY = ref(0)
const touchCurrentY = ref(0)
const isDragging = ref(false)
const dragOffset = ref(0)

// Computed style for drag animation
const sheetStyle = computed(() => {
  if (isDragging.value && dragOffset.value > 0) {
    return {
      transform: `translateY(${dragOffset.value}px)`,
      transition: 'none',
    }
  }
  return {}
})

// Touch handlers for swipe gestures
function onTouchStart(event: TouchEvent) {
  touchStartY.value = event.touches[0].clientY
  isDragging.value = true
}

function onTouchMove(event: TouchEvent) {
  if (!isDragging.value) return

  touchCurrentY.value = event.touches[0].clientY
  const deltaY = touchCurrentY.value - touchStartY.value

  // Only allow dragging down (positive delta)
  if (deltaY > 0 && !isMinimized.value) {
    dragOffset.value = deltaY
  }

  // Allow dragging up when minimized
  if (deltaY < 0 && isMinimized.value) {
    // Subtle feedback for upward drag
    dragOffset.value = Math.max(deltaY / 2, -30)
  }
}

function onTouchEnd() {
  if (!isDragging.value) return
  isDragging.value = false

  const deltaY = touchCurrentY.value - touchStartY.value

  // Swipe down to minimize
  if (deltaY > props.minimizeThreshold && !isMinimized.value) {
    minimize()
  }

  // Swipe up to expand
  if (deltaY < -50 && isMinimized.value) {
    expand()
  }

  // Reset drag offset
  dragOffset.value = 0
}

// Actions
function minimize() {
  isMinimized.value = true
  emit('minimize')
}

function expand() {
  isMinimized.value = false
  emit('expand')
}

function toggleMinimize() {
  if (isMinimized.value) {
    expand()
  } else {
    minimize()
  }
}

// Reset state when closed
watch(() => props.isOpen, (isOpen) => {
  if (!isOpen) {
    isDragging.value = false
    dragOffset.value = 0
    touchStartY.value = 0
    touchCurrentY.value = 0
  } else if (props.startMinimized) {
    isMinimized.value = true
  }
})

// Prevent body scroll when sheet is open and expanded
watch([() => props.isOpen, isMinimized], ([open, minimized]) => {
  if (open && !minimized) {
    document.body.style.overflow = 'hidden'
  } else {
    document.body.style.overflow = ''
  }
})

onUnmounted(() => {
  document.body.style.overflow = ''
})
</script>

<style scoped>
/* Backdrop */
.bottom-sheet-backdrop {
  @apply fixed inset-0 z-40 bg-black/40 backdrop-blur-sm;
}

/* Container */
.bottom-sheet-container {
  @apply fixed bottom-0 left-0 right-0 z-50;
  @apply bg-white rounded-t-2xl shadow-2xl;
  @apply max-h-[85vh] overflow-hidden;
  @apply transition-all duration-300 ease-out;
}

.bottom-sheet-container.is-minimized {
  @apply max-h-14;
  @apply shadow-lg;
}

/* Drag Handle */
.drag-handle {
  @apply flex flex-col items-center py-3 cursor-grab active:cursor-grabbing;
  @apply border-b border-gray-100;
}

.drag-indicator {
  @apply w-10 h-1 bg-gray-300 rounded-full;
}

.minimize-label {
  @apply mt-1 text-xs font-medium text-gray-500;
}

/* Sheet Content */
.sheet-content {
  @apply max-h-[calc(85vh-56px)] overflow-y-auto;
  @apply p-4;
}

/* Floating Restore Button */
.floating-restore-button {
  @apply fixed bottom-20 left-1/2 -translate-x-1/2 z-50;
  @apply flex items-center gap-2 px-4 py-2;
  @apply bg-blue-600 hover:bg-blue-700 text-white;
  @apply rounded-full shadow-lg;
  @apply font-medium text-sm;
  @apply transition-all duration-200;
  @apply focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-offset-2;
}

.button-label {
  @apply whitespace-nowrap;
}

/* Transitions */
.fade-enter-active,
.fade-leave-active {
  @apply transition-opacity duration-300;
}

.fade-enter-from,
.fade-leave-to {
  @apply opacity-0;
}

.slide-enter-active {
  @apply transition-transform duration-300 ease-out;
}

.slide-leave-active {
  @apply transition-transform duration-200 ease-in;
}

.slide-enter-from,
.slide-leave-to {
  @apply translate-y-full;
}

.pop-enter-active {
  @apply transition-all duration-300 ease-out;
}

.pop-leave-active {
  @apply transition-all duration-200 ease-in;
}

.pop-enter-from,
.pop-leave-to {
  @apply opacity-0 scale-75 translate-y-4;
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
  .bottom-sheet-container {
    @apply bg-gray-800;
  }

  .drag-handle {
    @apply border-gray-700;
  }

  .drag-indicator {
    @apply bg-gray-600;
  }

  .minimize-label {
    @apply text-gray-400;
  }
}

/* Desktop adjustments */
@media (min-width: 768px) {
  .bottom-sheet-container {
    @apply max-w-lg left-1/2 -translate-x-1/2 right-auto;
    @apply max-h-[70vh];
  }

  .bottom-sheet-container.is-minimized {
    @apply translate-x-0 left-auto right-4 rounded-t-xl;
    @apply max-w-xs;
  }

  .floating-restore-button {
    @apply bottom-6 right-6 left-auto translate-x-0;
  }
}
</style>
