<template>
  <view class="uni-swipe">
    <view 
      class="uni-swipe__content"
      :style="contentStyle"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd"
    >
      <slot />
    </view>
    <view class="uni-swipe__actions" :style="actionsStyle">
      <slot name="actions">
        <view 
          v-for="(action, index) in actions" 
          :key="index"
          class="uni-swipe__action"
          :style="{ backgroundColor: action.color }"
          @click="onActionClick(action)"
        >
          <text class="uni-swipe__action-text">{{ action.text }}</text>
        </view>
      </slot>
    </view>
  </view>
</template>

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

interface SwipeAction {
  text: string
  color: string
  key?: string
}

interface Props {
  actions?: SwipeAction[]
  threshold?: number
}

const props = withDefaults(defineProps<Props>(), {
  actions: () => [],
  threshold: 60
})

const emit = defineEmits<{
  click: [action: SwipeAction]
}>()

const offset = ref(0)
const startX = ref(0)
const startY = ref(0)
const isOpen = ref(false)
const maxOffset = ref(0)

const contentStyle = computed(() => ({
  transform: `translateX(${-offset.value}px)`,
  transition: isDragging.value ? 'none' : 'transform 0.3s'
}))

const actionsStyle = computed(() => ({
  width: `${offset.value}px`
}))

const isDragging = ref(false)

function onTouchStart(e: TouchEvent) {
  const touch = e.touches[0]
  startX.value = touch.clientX
  startY.value = touch.clientY
  isDragging.value = true
  maxOffset.value = props.actions.length * 80
}

function onTouchMove(e: TouchEvent) {
  if (!isDragging.value) return
  const touch = e.touches[0]
  const deltaX = startX.value - touch.clientX
  const deltaY = startY.value - touch.clientY

  if (Math.abs(deltaX) > Math.abs(deltaY)) {
    e.preventDefault()
    offset.value = Math.min(Math.max(deltaX, 0), maxOffset.value)
  }
}

function onTouchEnd() {
  isDragging.value = false
  if (offset.value > props.threshold) {
    offset.value = maxOffset.value
    isOpen.value = true
  } else {
    offset.value = 0
    isOpen.value = false
  }
}

function onActionClick(action: SwipeAction) {
  offset.value = 0
  isOpen.value = false
  emit('click', action)
}

function close() {
  offset.value = 0
  isOpen.value = false
}

defineExpose({ close })
</script>

<style scoped>
.uni-swipe {
  position: relative;
  overflow: hidden;
}
.uni-swipe__content {
  position: relative;
  z-index: 1;
  background-color: #fff;
}
.uni-swipe__actions {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  overflow: hidden;
}
.uni-swipe__action {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80px;
  height: 100%;
}
.uni-swipe__action-text {
  color: #fff;
  font-size: 14px;
}
</style>
