<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from "vue";
import { globalState, getAudio, playSong, saveVolume } from "../composables/musicManager";
import PauseMusicController from "./PauseMusicController.vue";
import PlayingMusicController from "./PlayingMusicController.vue";

const props = defineProps<{
  id: string; title?: string; artist?: string;
  type?: 'netease' | 'local'; autoplay?: boolean;
  lrc?: string;
}>();

const currentTime = ref(0);
const duration = ref(0);
const finalUrl = ref("");
const coverImg = ref("");
const lastVolume = ref(globalState.volume || 50);
const isMobile = ref(false);

// --- 响应式 & 判定逻辑 ---
const checkMobile = () => { isMobile.value = window.innerWidth <= 640; };

// 分区域判定函数：电脑端 1/3，手机端 5/9
const checkInBounds = (clientX: number) => {
  const width = window.innerWidth;
  const ratio = isMobile.value ? (5 / 9) : (1 / 3);
  const sideMargin = (1 - ratio) / 2;
  return clientX >= width * sideMargin && clientX <= width * (1 - sideMargin);
};

// --- 播放模式 ---
const loopMode = ref<'all' | 'one'>('one');
const toggleLoopMode = () => {
  loopMode.value = loopMode.value === 'all' ? 'one' : 'all';
  const audio = getAudio();
  if (audio && globalState.playingId === props.id) audio.loop = loopMode.value === 'one';
};

// --- 歌词逻辑 ---
interface LyricLine { time: number; text: string; }
const lyrics = ref<LyricLine[]>([]);
const currentLineIndex = ref(0);
const isInteracting = ref(false);
const scrollOffset = ref(0);
const LINE_HEIGHT = 44;
const DEFAULT_HEIGHT = 132;

const lyricHeight = ref(DEFAULT_HEIGHT);
const isResizing = ref(false);
const BASE_CTRL_HEIGHT = 110;

const totalCardHeight = computed(() => {
  return (lyrics.value.length > 0 && lyricHeight.value > 0)
      ? BASE_CTRL_HEIGHT + lyricHeight.value
      : BASE_CTRL_HEIGHT;
});

// --- 交互核心逻辑 (支持电脑/手机分区) ---
let touchStartY = 0;
let isInternalAction = false;

const finalizeProgress = () => {
  const movedLines = Math.round(scrollOffset.value / LINE_HEIGHT);
  let targetIndex = Math.max(0, Math.min(currentLineIndex.value - movedLines, lyrics.value.length - 1));
  const audio = getAudio();
  if (audio && globalState.playingId === props.id) {
    audio.currentTime = lyrics.value[targetIndex].time;
  }
  isInteracting.value = false;
  scrollOffset.value = 0;
  isInternalAction = false;
};

// 鼠标滚轮逻辑 (电脑专用)
const onWheel = (e: WheelEvent) => {
  if (isResizing.value || lyrics.value.length === 0 || lyricHeight.value === 0) return;
  if (!checkInBounds(e.clientX)) return; // 非中间 1/3 区域不触发

  e.preventDefault();
  isInteracting.value = true;
  scrollOffset.value -= e.deltaY * 0.5;

  clearTimeout((window as any).wheelTimer);
  (window as any).wheelTimer = setTimeout(finalizeProgress, 300);
};

// 触摸/点击开始
const handleActionStart = (clientX: number, clientY: number) => {
  if (lyricHeight.value === 0) return;
  if (checkInBounds(clientX)) {
    isInternalAction = true;
    isInteracting.value = true;
    touchStartY = clientY;
  }
};

const onTouchStart = (e: TouchEvent) => handleActionStart(e.touches[0].clientX, e.touches[0].clientY);
const onTouchMove = (e: TouchEvent) => {
  if (!isInternalAction || !isInteracting.value) return;
  if (e.cancelable) e.preventDefault();
  scrollOffset.value = e.touches[0].clientY - touchStartY;
};
const onEnd = (e: TouchEvent | MouseEvent) => {
  if (isInternalAction) finalizeProgress();
  if (e.currentTarget) (e.currentTarget as HTMLElement).style.transform = '';
};

// --- 基础逻辑恢复 ---
const startResize = (e: MouseEvent | TouchEvent) => {
  if (lyrics.value.length === 0) return;
  isResizing.value = true;
  const sY = 'touches' in e ? e.touches[0].clientY : e.clientY;
  const sH = lyricHeight.value;
  const onMove = (mv: MouseEvent | TouchEvent) => {
    const curY = 'touches' in mv ? mv.touches[0].clientY : mv.clientY;
    const newH = sH + (curY - sY);
    if (newH < DEFAULT_HEIGHT / 2) lyricHeight.value = 0;
    else lyricHeight.value = Math.max(DEFAULT_HEIGHT, Math.min(600, newH));
  };
  const onStop = () => {
    isResizing.value = false;
    window.removeEventListener('mousemove', onMove as any); window.removeEventListener('mouseup', onStop);
    window.removeEventListener('touchmove', onMove as any); window.removeEventListener('touchend', onStop);
  };
  window.addEventListener('mousemove', onMove as any); window.addEventListener('mouseup', onStop);
  window.addEventListener('touchmove', onMove as any, { passive: false }); window.addEventListener('touchend', onStop);
};

const toggleLyricHeight = () => {
  if (lyricHeight.value > DEFAULT_HEIGHT) lyricHeight.value = DEFAULT_HEIGHT;
  else if (lyricHeight.value === DEFAULT_HEIGHT) lyricHeight.value = 0;
  else lyricHeight.value = DEFAULT_HEIGHT;
};

const lyricTransformY = computed(() => {
  if (lyricHeight.value === 0) return 0;
  return (lyricHeight.value / 2) - (currentLineIndex.value * LINE_HEIGHT + LINE_HEIGHT / 2) + scrollOffset.value;
});

const handleMuteToggle = () => {
  if (globalState.volume > 0) { lastVolume.value = globalState.volume; saveVolume(0); }
  else { saveVolume(lastVolume.value || 50); }
};

const parseLRC = (lrcStr: string) => {
  if (!lrcStr || lrcStr.trim() === "") return [];
  const lines = lrcStr.split('\n');
  const result: LyricLine[] = [];
  const timeExp = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/;
  for (const line of lines) {
    const match = timeExp.exec(line);
    if (match) {
      const time = parseInt(match[1]) * 60 + parseInt(match[2]) + parseInt(match[3]) / (match[3].length === 3 ? 1000 : 100);
      const text = line.replace(timeExp, '').trim();
      if (text) result.push({ time, text });
    }
  }
  return result.sort((a, b) => a.time - b.time);
};

const initSource = async () => {
  if (props.lrc) { lyrics.value = parseLRC(props.lrc); }
  else if (props.type === 'netease') {
    try {
      const lrcRes = await fetch(`https://api.i-meto.com/meting/api?server=netease&type=lrc&id=${props.id}`);
      lyrics.value = parseLRC(await lrcRes.text());
    } catch (e) { lyrics.value = []; }
  }
  if (props.type === 'netease') {
    try {
      const res = await fetch(`https://api.i-meto.com/meting/api?server=netease&type=song&id=${props.id}`);
      const data = await res.json();
      if (data?.[0]) {
        coverImg.value = data[0].pic.replace("http://", "https://");
        finalUrl.value = data[0].url.replace("http://", "https://");
      }
    } catch (e) { finalUrl.value = `https://music.163.com/song/media/outer/url?id=${props.id}.mp3`; }
  } else if (props.type === 'local') {
    finalUrl.value = `/music/${props.id}.mp3`; coverImg.value = `/music/${props.id}.jpg`;
  }
  if (props.autoplay) setTimeout(() => togglePlay(new Event('click')), 500);
};

const togglePlay = (e: Event) => {
  e.stopPropagation(); const audio = getAudio();
  if (!audio || !finalUrl.value) return;
  if (globalState.playingId === props.id && globalState.isPlayed) audio.pause();
  else {
    playSong(props.id, finalUrl.value, { title: props.title, artist: props.artist, cover: coverImg.value });
    audio.loop = loopMode.value === 'one';
  }
};

onMounted(() => {
  globalState.activeInstances++; initSource(); checkMobile();
  window.addEventListener('resize', checkMobile);
  getAudio()?.addEventListener('timeupdate', () => {
    const audio = getAudio();
    if (audio && globalState.playingId === props.id) { currentTime.value = audio.currentTime; duration.value = audio.duration || 0; }
  });
});
onUnmounted(() => { globalState.activeInstances--; window.removeEventListener('resize', checkMobile); });

watch(currentTime, (newTime) => {
  if (lyrics.value.length === 0 || isInteracting.value) return;
  const index = lyrics.value.findIndex((line, i) => {
    const next = lyrics.value[i + 1]; return newTime >= line.time && (!next || newTime < next.time);
  });
  if (index !== -1) currentLineIndex.value = index;
});

const formatTime = (s: number) => {
  if (!s || isNaN(s)) return "00:00";
  return `${Math.floor(s/60).toString().padStart(2, '0')}:${Math.floor(s%60).toString().padStart(2, '0')}`;
};
</script>

<template>
  <ClientOnly>
    <div class="music-card-master" :class="{ 'is-resizing': isResizing, 'mobile-mode': isMobile }" :style="{ height: totalCardHeight + 'px' }">
      <div class="main-layout" :style="{ height: '100%' }">
        <div class="player-left" :style="{ justifyContent: (lyrics.length > 0 && lyricHeight > 0) ? 'flex-start' : 'center' }">
          <div class="music-card-pro">
            <div class="disk-part" @click="togglePlay">
              <div class="disk-base">
                <img :src="coverImg" class="album-img" :class="{ 'rotate': globalState.isPlayed && globalState.playingId === id }" />
                <div class="state-overlay">
                  <PlayingMusicController v-if="globalState.isPlayed && globalState.playingId === id" />
                  <PauseMusicController v-else />
                </div>
              </div>
            </div>

            <div class="main-content">
              <div class="meta-row">
                <span class="song-name">{{ title || '加载中...' }}</span>
                <span class="artist-name" v-if="artist">{{ artist }}</span>
              </div>
              <div class="progress-container">
                <span class="time-label">{{ formatTime(currentTime) }}</span>
                <div class="range-wrapper">
                  <input type="range" class="range-input" :max="duration || 100" :value="currentTime"
                         @input="e => { if (globalState.playingId === id) getAudio()!.currentTime = Number((e.target as HTMLInputElement).value) }" />
                </div>
                <span class="time-label">{{ formatTime(duration) }}</span>
              </div>
            </div>

            <div class="action-side">
              <div class="btn-stack">
                <div class="tool-btn" @click="toggleLoopMode" @touchend="onEnd"
                     :title="loopMode === 'one' ? '当前：单曲循环\n点击切换顺序播放' : '当前：顺序播放\n点击切换单曲循环'">
                  <span>{{ loopMode === 'one' ? '🔄' : '1️⃣' }}</span>
                </div>
                <div class="tool-btn" v-if="lyrics.length > 0" @click="toggleLyricHeight" @touchend="onEnd"
                     :title="lyricHeight === 0 ? '展开歌词' : '收起歌词'">
                  <span>{{ lyricHeight === 0 ? '🔽' : '🔼' }}</span>
                </div>
              </div>
            </div>
          </div>

          <div v-if="lyrics.length > 0 && lyricHeight > 0" class="lyric-view-bar-3"
               :style="{ height: lyricHeight + 'px' }" @wheel="onWheel"
               @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onEnd">
            <div class="lyric-wrapper" :style="{ transform: `translateY(${lyricTransformY}px)`, transition: (isInteracting || isResizing) ? 'none' : 'transform 0.4s ease' }">
              <div v-for="(line, index) in lyrics" :key="index" class="lyric-line" :class="{ 'is-active': currentLineIndex === index }">{{ line.text }}</div>
            </div>
          </div>
        </div>

        <div class="volume-side" v-if="!isMobile">
          <div class="v-slider-wrapper">
            <input type="range" :value="globalState.volume" min="0" max="100" class="v-slider"
                   :style="{ height: (totalCardHeight - 48) + 'px' }"
                   @input="e => saveVolume(Number((e.target as HTMLInputElement).value))" />
          </div>
          <div class="mute-icon" @click="handleMuteToggle">
            {{ globalState.volume == 0 ? '🔇' : '🔊' }}
          </div>
        </div>
      </div>
      <div v-if="lyrics.length > 0" class="master-resize-handle" @mousedown="startResize" @touchstart.prevent="startResize">
        <div class="handle-line"></div>
      </div>
    </div>
  </ClientOnly>
</template>

<style scoped lang="scss">
// --- 电脑端样式 (完全还原你提供的版本) ---
.music-card-master {
  margin: 1.5rem 0; background: var(--vp-c-bg-soft); border: 1px solid var(--vp-c-divider);
  border-radius: 16px; overflow: hidden; position: relative;
  transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  &.is-resizing { cursor: ns-resize; transition: none; }
}
.main-layout { display: flex; align-items: stretch; width: 100%; }
.player-left { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100%; }
.music-card-pro { display: flex; align-items: center; gap: 24px; padding: 20px 28px; min-height: 110px; background: var(--vp-c-bg-soft); z-index: 2; }
.disk-part { flex-shrink: 0; .disk-base { width: 68px; height: 68px; border-radius: 50%; overflow: hidden; position: relative; background: #000; box-shadow: 0 4px 15px rgba(0,0,0,0.25); } .album-img { width: 100%; height: 100%; object-fit: cover; &.rotate { animation: rotating 12s linear infinite; } } .state-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0.15); color: #fff; font-size: 20px; } }
@keyframes rotating { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

.main-content {
  flex: 1; min-width: 0;
  .meta-row {
    display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px;
    .song-name { font-weight: 700; font-size: 18px; color: var(--vp-c-text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .artist-name { font-size: 14px; color: var(--vp-c-text-2); opacity: 0.8; }
  }
}
.progress-container { display: flex; align-items: center; gap: 14px; .time-label { font-size: 12px; min-width: 40px; font-family: monospace; opacity: 0.6; } .range-wrapper { flex: 1; display: flex; align-items: center; } }
.range-input { width: 100%; accent-color: var(--vp-c-brand); cursor: pointer; height: 5px; }

.action-side { margin-left: auto; .btn-stack { display: flex; flex-direction: column; gap: 8px; } .tool-btn { width: 38px; height: 38px; border: none; background: transparent; cursor: pointer; font-size: 20px; display: flex; align-items: center; justify-content: center; transition: transform 0.2s; &:hover { transform: scale(1.2); } &:active { transform: scale(0.9); } } }

.lyric-view-bar-3 {
  border-top: 1px solid var(--vp-c-divider); overflow: hidden; position: relative;
  mask-image: linear-gradient(to bottom, transparent, black 20%, black 80%, transparent);
  .lyric-line { height: 44px; line-height: 44px; font-size: 16px; color: var(--vp-c-text-1); opacity: 0.3; text-align: center; transition: all 0.3s; &.is-active { opacity: 1; color: var(--vp-c-brand); font-weight: 600; transform: scale(1.05); } }
}

.volume-side { width: 48px; border-left: 1px solid var(--vp-c-divider); display: flex; flex-direction: column; justify-content: space-between; align-items: center; padding: 8px 0; background: rgba(0,0,0,0.02); box-sizing: border-box; .v-slider-wrapper { width: 100%; display: flex; justify-content: center; align-items: flex-start; flex: 1; } .v-slider { writing-mode: vertical-lr; direction: rtl; appearance: auto; width: 6px; cursor: pointer; accent-color: var(--vp-c-brand); } .mute-icon { height: 24px; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 16px; opacity: 0.7; transition: all 0.2s; &:hover { opacity: 1; transform: scale(1.1); } } }

.master-resize-handle { position: absolute; bottom: 0; left: 0; right: 0; height: 12px; cursor: ns-resize; display: flex; align-items: center; justify-content: center; .handle-line { width: 45px; height: 4px; border-radius: 2px; background: transparent; transition: 0.3s; } &:hover .handle-line { background: var(--vp-c-divider); width: 65px; } }

// --- 手机端适配 (独立于电脑端) ---
.mobile-mode {
  .music-card-pro {
    padding: 15px 20px; gap: 15px;
    .disk-part .disk-base { width: 56px; height: 56px; }
    .main-content {
      .meta-row { flex-direction: column; gap: 2px; .song-name { font-size: 16px; } .artist-name { font-size: 12px; } }
      .progress-container { gap: 10px; }
    }
    .action-side .btn-stack { gap: 12px; }
  }
  .lyric-view-bar-3 { mask-image: linear-gradient(to bottom, transparent, black 40%, black 60%, transparent); }
}
</style>