<template>
  <view
    v-if="positionReady"
    class="music-player"
    :style="playerStyle"
    @touchstart.stop="handleTouchStart"
    @touchmove.stop.prevent="handleTouchMove"
    @touchend.stop="handleTouchEnd"
    @touchcancel.stop="handleTouchEnd"
  >
    <view
      class="music-toggle"
      :class="{ playing: isPlaying, dragging: isDragging }"
      @click="toggleMusic"
    >
      <view class="music-disc" :class="{ spinning: isPlaying }"></view>
      <view class="music-note"></view>
    </view>
  </view>
</template>

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

const isPlaying = ref(false)
const positionReady = ref(false)
const isDragging = ref(false)
const playerPosition = ref({ x: 0, y: 0 })
let audioInstance = null
let windowMetrics = {
  width: 375,
  height: 667,
  statusBarHeight: 20,
  safeAreaBottom: 0,
  buttonSize: 44
}
let dragStart = null
let suppressNextClick = false

// 背景音乐 URL - 使用原型中的音乐
const MUSIC_URL = 'https://v3b.fal.media/files/b/0a8c9a0b/rStj8V-2tCe6bVYpCCcLN_output.mp3'
const STORAGE_KEY = 'music_player_position'

const playerStyle = computed(() => ({
  left: `${playerPosition.value.x}px`,
  top: `${playerPosition.value.y}px`
}))

const rpxToPx = (rpx, windowWidth = windowMetrics.width) => windowWidth * rpx / 750

const clamp = (value, min, max) => Math.max(min, Math.min(max, value))

const clampPosition = (position) => {
  const margin = 8
  const minY = Math.max(margin, windowMetrics.statusBarHeight + 8)
  const maxX = windowMetrics.width - windowMetrics.buttonSize - margin
  const maxY = windowMetrics.height - windowMetrics.safeAreaBottom - windowMetrics.buttonSize - margin
  return {
    x: clamp(Number(position?.x) || margin, margin, Math.max(margin, maxX)),
    y: clamp(Number(position?.y) || minY, minY, Math.max(minY, maxY))
  }
}

const savePosition = () => {
  uni.setStorageSync(STORAGE_KEY, playerPosition.value)
}

const restorePosition = () => {
  const saved = uni.getStorageSync(STORAGE_KEY)
  if (saved && typeof saved === 'object') {
    playerPosition.value = clampPosition(saved)
    return
  }
  playerPosition.value = clampPosition({
    x: windowMetrics.width - windowMetrics.buttonSize - rpxToPx(16),
    y: windowMetrics.height - windowMetrics.safeAreaBottom - windowMetrics.buttonSize - 96
  })
}

const initAudio = () => {
  if (!audioInstance) {
    audioInstance = uni.createInnerAudioContext()
    audioInstance.src = MUSIC_URL
    audioInstance.loop = true
    audioInstance.autoplay = false

    audioInstance.onPlay(() => {
      isPlaying.value = true
    })

    audioInstance.onPause(() => {
      isPlaying.value = false
    })

    audioInstance.onError((err) => {
      console.error('音乐播放失败:', err)
      isPlaying.value = false
      uni.showToast({ title: '音乐资源暂不可用', icon: 'none' })
    })

    audioInstance.onEnded(() => {
      isPlaying.value = false
    })
  }
}

const toggleMusic = async () => {
  if (suppressNextClick || isDragging.value) return
  initAudio()

  if (isPlaying.value) {
    audioInstance.pause()
  } else {
    try {
      audioInstance.play()
    } catch (err) {
      console.error('音乐播放失败:', err)
      isPlaying.value = false
    }
  }
}

const handleTouchStart = (event) => {
  const touch = event.touches?.[0]
  if (!touch) return
  dragStart = {
    x: touch.clientX,
    y: touch.clientY,
    originX: playerPosition.value.x,
    originY: playerPosition.value.y,
    moved: false
  }
}

const handleTouchMove = (event) => {
  const touch = event.touches?.[0]
  if (!touch || !dragStart) return
  const deltaX = touch.clientX - dragStart.x
  const deltaY = touch.clientY - dragStart.y
  if (Math.abs(deltaX) > 3 || Math.abs(deltaY) > 3) {
    dragStart.moved = true
    isDragging.value = true
  }
  if (!dragStart.moved) return
  playerPosition.value = clampPosition({
    x: dragStart.originX + deltaX,
    y: dragStart.originY + deltaY
  })
}

const handleTouchEnd = () => {
  if (dragStart?.moved) {
    playerPosition.value = clampPosition(playerPosition.value)
    savePosition()
    suppressNextClick = true
    setTimeout(() => {
      suppressNextClick = false
    }, 180)
  }
  dragStart = null
  isDragging.value = false
}

onMounted(() => {
  const windowInfo = uni.getWindowInfo ? uni.getWindowInfo() : uni.getSystemInfoSync()
  windowMetrics = {
    width: windowInfo.windowWidth || 375,
    height: windowInfo.windowHeight || 667,
    statusBarHeight: windowInfo.statusBarHeight || 20,
    safeAreaBottom: windowInfo.safeAreaInsets?.bottom || 0,
    buttonSize: rpxToPx(88, windowInfo.windowWidth || 375)
  }
  restorePosition()
  positionReady.value = true
})

onUnmounted(() => {
  if (audioInstance) {
    audioInstance.stop()
    audioInstance.destroy()
  }
})

defineExpose({
  toggleMusic,
  isPlaying
})
</script>

<style scoped>
.music-player {
  position: fixed;
  z-index: 1000;
  width: 88rpx;
  height: 88rpx;
}

.music-toggle {
  width: 88rpx;
  height: 88rpx;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
  opacity: 0.4;
}

.music-toggle.dragging {
  transform: scale(1.06);
  opacity: 0.78;
  border-color: rgba(216, 180, 254, 0.42);
  box-shadow: 0 0 34rpx rgba(168, 85, 247, 0.32);
}

.music-toggle:active {
  transform: scale(0.95);
  opacity: 0.6;
}

.music-toggle.playing {
  opacity: 1;
  border-color: rgba(168, 85, 247, 0.5);
  box-shadow: 0 0 30rpx rgba(168, 85, 247, 0.3);
}

.music-disc {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(168, 85, 247, 0.2);
  transition: all 0.3s ease;
}

.music-disc.spinning {
  animation: spin 3s linear infinite;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.music-note {
  position: relative;
  width: 26rpx;
  height: 38rpx;
  z-index: 1;
}

.music-note::before {
  content: '';
  position: absolute;
  left: 2rpx;
  bottom: 0;
  width: 18rpx;
  height: 14rpx;
  border: 5rpx solid rgba(196, 181, 253, 0.86);
  border-radius: 50%;
}

.music-note::after {
  content: '';
  position: absolute;
  right: 0;
  top: 0;
  width: 9rpx;
  height: 34rpx;
  border-radius: 6rpx;
  background: rgba(196, 181, 253, 0.86);
  box-shadow: 8rpx 3rpx 0 rgba(196, 181, 253, 0.42);
}
</style>
