<script setup lang="ts">
// [导入] 依赖项和类型
import { SongFrom, SongRequestOption, SongsInfo } from '@/api/api-models'; // API 数据模型
import { QueryGetAPI, QueryPostAPI } from '@/api/query'; // API 请求方法
import { SONG_API_URL } from '@/data/constants'; // API 地址常量
import { GetPlayButton } from '@/Utils'; // 公用方法：获取播放/信息按钮
import SongPlayer from './SongPlayer.vue'; // 子组件：歌曲播放器

// [导入] UI 组件和图标
import {
  Delete24Filled,
  Info24Filled,
  NotepadEdit20Filled,
  Play24Filled
} from '@vicons/fluent';
import { useLocalStorage, refDebounced } from '@vueuse/core'; // VueUse 工具函数
import { List } from 'linqts'; // LINQ for TypeScript
import {
  DataTableBaseColumn,
  DataTableColumns,
  DataTableRowKey,
  FormInst,
  FormRules,
  NButton,
  NCard,
  NCheckbox,
  NDataTable,
  NDivider,
  NEllipsis,
  NForm,
  NFormItem,
  NIcon,
  NInput,
  NInputGroup,
  NInputGroupLabel,
  NInputNumber,
  NModal,
  NPopconfirm,
  NSelect,
  NSpace,
  NTabPane,
  NTabs,
  NTag,
  NText,
  NTooltip,
  useMessage, // Naive UI 组件
} from 'naive-ui';
import { VNodeChild, computed, h, onMounted, ref, watch } from 'vue'; // Vue 核心 API

// --- Props 定义 ---
const props = defineProps<{
  songs: SongsInfo[] // 歌曲列表数据
  canEdit?: boolean // 是否允许编辑（通常用于区分查看模式和管理模式）
  isSelf: boolean // 是否为用户自己的歌单（控制编辑/删除权限）
  extraButton?: (song: SongsInfo) => VNodeChild[] // 允许外部传入额外的操作按钮函数
}>()

// --- 响应式状态 ---
const message = useMessage() // Naive UI 消息提示
const volume = useLocalStorage('Settings.AplayerVolume', 0.8) // 播放器音量，持久化存储
const songsInternal = ref<SongsInfo[]>([]) // 内部维护的歌曲列表，避免直接修改 props
const playingSong = ref<SongsInfo>() // 当前正在试听的歌曲
const isLrcLoading = ref<string>() // 歌词加载状态（存储歌曲 key）
const isLoading = ref(false) // 通用加载状态 (用于 API 请求)
const pageSize = ref(25) // 每页大小

// --- 搜索与筛选状态 ---
const searchMusicKeyword = ref('') // 歌曲名称搜索关键词
const debouncedInput = refDebounced(searchMusicKeyword, 500) // 防抖处理的搜索关键词
const selectedLanguageFilter = ref<string[]>([]) // 顶部语言筛选器选中值
const selectedTagFilter = ref<string[]>([])      // 顶部标签筛选器选中值
const selectedAuthorFilter = ref<string | null>(null) // 顶部作者筛选器选中值 (直接控制列筛选)

// --- 弹窗状态 ---
const showModal = ref(false) // 单个歌曲编辑弹窗显示状态
const showBatchModal = ref(false) // 批量编辑弹窗显示状态
const updateSongModel = ref<SongsInfo>({} as SongsInfo) // 单个歌曲编辑表单数据模型
const formRef = ref<FormInst | null>(null) // 单个歌曲编辑表单实例引用

// --- 批量编辑状态 ---
const batchUpdate_Author = ref<string[]>([]) // 批量编辑 - 作者
const batchUpdate_Tag = ref<string[]>([]) // 批量编辑 - 标签
const batchUpdate_Language = ref<string[]>([]) // 批量编辑 - 语言
const batchUpdate_Option = ref<SongRequestOption | undefined>() // 批量编辑 - 点歌选项

// --- 表格状态 ---
const columns = ref<DataTableColumns<SongsInfo>>() // 表格列定义
const selectedColumn = ref<DataTableRowKey[]>([]) // 表格选中行的 Key 数组

// --- 计算属性 ---

// 筛选后的歌曲列表
const songsComputed = computed(() => {
  let filteredSongs = songsInternal.value;

  // 1. 搜索框筛选 (曲名或翻译名，防抖)
  const searchTerm = debouncedInput.value?.trim().toLowerCase();
  if (searchTerm) {
    filteredSongs = filteredSongs.filter((s) =>
      s.name.toLowerCase().includes(searchTerm) ||
      s.translateName?.toLowerCase().includes(searchTerm) // 同时搜索翻译名称
    );
  }

  // 2. 顶部语言筛选
  if (selectedLanguageFilter.value.length > 0) {
    filteredSongs = filteredSongs.filter((s) =>
      s.language?.some(lang => selectedLanguageFilter.value.includes(lang))
    );
  }

  // 3. 顶部标签筛选
  if (selectedTagFilter.value.length > 0) {
    filteredSongs = filteredSongs.filter((s) =>
      s.tags?.some(tag => selectedTagFilter.value.includes(tag))
    );
  }

  // 注意: 作者筛选主要通过列筛选器实现 (由 selectedAuthorFilter 控制)
  // 如果需要整合到这里，需要额外逻辑

  return filteredSongs;
});


// 语言下拉选项 (包含预设和歌曲数据中存在的)
const languageSelectOption = computed(() => {
  const languages = new Set<string>([ // 预设一些常用语言
    '中文', '日语', '英语', '韩语', '法语', '西语', '其他'
  ])
  songsInternal.value.forEach((s) => {
    s.language?.forEach((l) => languages.add(l))
  })
  return [...languages].sort().map((t) => ({ // 排序增加用户体验
    label: t,
    value: t,
  }))
})

// 标签下拉选项 (从歌曲数据中动态生成)
const tagsSelectOption = computed(() => {
  return new List(songsInternal.value)
    .SelectMany((s) => new List(s?.tags ?? [])) // 使用 ?? [] 避免 undefined
    .Distinct()
    .OrderBy(tag => tag) // 排序
    .ToArray()
    .map((t) => ({
      label: t,
      value: t,
    }))
})

// 作者下拉选项 (从歌曲数据中动态生成)
const authorsOptions = computed(() => {
  return new List(songsInternal.value)
    .SelectMany((s) => new List(s?.author ?? [])) // 使用 ?? [] 避免 undefined
    .Distinct()
    .OrderBy(author => author) // 排序
    .ToArray()
    .map((t) => ({
      label: t,
      value: t,
    }))
})

// --- 表格列定义 ---

// 作者列定义 (包含筛选逻辑)
const authorColumn = ref<DataTableBaseColumn<SongsInfo>>({
  title: '作者',
  key: 'author', // key 应该对应数据字段，虽然这里是数组，但用于标识
  width: 200,
  resizable: true,
  // 列筛选函数：检查行的作者数组是否包含筛选值
  filter(value, row) {
    return row.author?.includes(value.toString()) ?? false;
  },
  // 列筛选选项：使用计算属性动态生成
  filterOptions: authorsOptions.value, // 初始值
  // 列筛选值：受顶部的 selectedAuthorFilter 控制
  filterOptionValue: selectedAuthorFilter.value,
  render(data) {
    // 渲染作者按钮，点击时更新列筛选状态
    return h(NSpace, { size: 5 }, () =>
      data.author?.map((a) => // 使用 ?. 防止 author 为空
        h(NButton, { size: 'tiny', type: 'info', secondary: true, onClick: () => onAuthorClick(a) }, () => a),
      ) ?? null // 如果 author 为空则不渲染
    )
  },
})

// 点击作者按钮的处理函数：更新列筛选值
const onAuthorClick = (author: string) => {
  if (authorColumn.value.filterOptionValue === author) {
    // 如果当前筛选值就是点击的作者，则清除筛选
    authorColumn.value.filterOptionValue = null;
    selectedAuthorFilter.value = null; // 同步更新顶部筛选状态
  } else {
    // 否则，设置筛选值为点击的作者
    authorColumn.value.filterOptionValue = author;
    selectedAuthorFilter.value = author; // 同步更新顶部筛选状态
  }
}

// 监听顶部作者筛选器变化，更新列筛选状态
watch(selectedAuthorFilter, (newVal) => {
  authorColumn.value.filterOptionValue = newVal;
});

// 创建表格列配置的函数
function createColumns(): DataTableColumns<SongsInfo> {
  // 更新作者列的筛选选项和当前筛选值 (确保响应性)
  authorColumn.value.filterOptions = authorsOptions.value
  authorColumn.value.filterOptionValue = selectedAuthorFilter.value

  return [
    {
      type: 'selection', // 复选框列
      disabled: () => !props.isSelf, // 只有自己的歌单才允许选择 (用于批量操作)
    },
    {
      key: 'name', // 对应 SongsInfo 的 name 字段
      title: '曲名',
      resizable: true,
      minWidth: 150, // 增加最小宽度
      width: 300,
      sorter: 'default', // 启用默认排序
      render(data) {
        // 同时显示原名和翻译名 (如果存在)
        return h(NSpace, { vertical: true, size: 0, wrap: false }, () => [
          h(NText, { style: { color: data.options?.scMinPrice ? '#c36767' : '' } }, () => data.name), // SC 歌曲标红
          data.translateName ? h(NText, { depth: '3', style: { fontSize: '12px' } }, () => data.translateName) : null, // 显示翻译名
        ])
      },
    },
    authorColumn.value, // 作者列 (已包含筛选)
    {
      title: '语言',
      key: 'language',
      width: 150,
      resizable: true,
      // 列筛选选项 (使用预设 + 动态生成)
      filterOptions: languageSelectOption.value,
      // 列筛选函数
      filter(value, row) {
        return row.language?.includes(value.toString()) ?? false;
      },
      render(data) {
        // 使用 NTag 显示语言
        return data.language?.length // 使用 ?.length 检查
          ? h(NSpace, { size: 5 }, () =>
            data.language?.map((a) => h(NTag, { bordered: false, size: 'small' }, () => a)),
          )
          : null
      },
    },
    {
      title: '描述',
      key: 'description',
      minWidth: 100, // 增加最小宽度
      resizable: true,
      ellipsis: { // 使用 Naive UI 的省略配置
        tooltip: true // 鼠标悬浮显示完整内容
      }
      // render(data) { // 使用 ellipsis 配置后，不再需要手动渲染 NEllipsis
      //   return h(NEllipsis, { tooltip: { placement: 'top'} }, () => data.description)
      // },
    },
    {
      title: '点歌要求', // 标题修改，更清晰
      key: 'options',
      width: 180, // 调整宽度
      resizable: true,
      render(data) {
        // 渲染点歌要求的标签
        const tags: VNodeChild[] = []
        if (!data.options) return null; // 没有选项直接返回

        if (data.options.needJianzhang) {
          tags.push(h(NTag, { color: { textColor: 'white', color: GetGuardColor(3), borderColor: 'white' }, size: 'small' }, () => '舰长'))
        }
        if (data.options.needTidu) {
          tags.push(h(NTag, { color: { textColor: 'white', color: GetGuardColor(2), borderColor: 'white' }, size: 'small' }, () => '提督'))
        }
        if (data.options.needZongdu) {
          tags.push(h(NTag, { color: { textColor: 'white', color: GetGuardColor(1), borderColor: 'white' }, size: 'small' }, () => '总督'))
        }
        if (data.options.scMinPrice) {
          tags.push(h(NTag, { color: { textColor: 'white', color: GetSCColor(data.options.scMinPrice), borderColor: 'white' }, size: 'small' }, () => `SC ≥ ${data.options?.scMinPrice}`)) // 优化显示
        }
        if (data.options.fanMedalMinLevel) {
          tags.push(h(NTag, { type: 'info', size: 'small' }, () => `粉丝牌 ≥ ${data.options?.fanMedalMinLevel}`)) // 优化显示
        }
        return tags.length > 0 ? h(NSpace, { size: 5 }, () => tags) : null;
      },
    },
    {
      title: '标签',
      key: 'tags',
      width: 150, // 调整宽度
      resizable: true,
      // 列筛选选项
      filterOptions: tagsSelectOption.value,
      // 列筛选函数
      filter(value, row) {
        return row.tags?.includes(value.toString()) ?? false;
      },
      render(data) {
        // 使用 NTag 显示标签
        return data.tags?.length
          ? h(NSpace, { size: 5 }, () => data.tags?.map((a) => h(NTag, { bordered: false, size: 'small' }, () => a)))
          : null
      },
    },
    {
      title: '操作',
      key: 'manage',
      width: props.isSelf ? 170 : 120, // 根据是否自己的歌单调整宽度
      fixed: 'right', // 固定操作列在右侧
      render(data) {
        const buttons: VNodeChild[] = [];

        // 1. 获取播放/信息按钮 (来自 Utils)
        const playButton = GetPlayButton(data);
        if (playButton) buttons.push(playButton);

        // 2. 试听按钮 (仅对音频文件显示)
        const isAudio = /\.(mp3|flac|ogg|wav|m4a)$/i.test(data.url ?? ''); // 正则判断音频后缀
        if (isAudio) {
          buttons.push(
            h(NTooltip, null, {
              trigger: () =>
                h(
                  NButton,
                  {
                    type: 'primary',
                    size: 'small',
                    circle: true,
                    loading: isLrcLoading.value === data.key, // 绑定加载状态
                    onClick: () => { playingSong.value = data }, // 点击播放
                  },
                  { icon: () => h(NIcon, { component: Play24Filled }) }
                ),
              default: () => '试听',
            })
          );
        }

        // 3. 编辑和删除按钮 (仅自己的歌单显示)
        if (props.isSelf) {
          buttons.push(
            h(NTooltip, null, {
              trigger: () =>
                h(
                  NButton,
                  {
                    size: 'small',
                    circle: true,
                    secondary: true, // 次要按钮样式
                    onClick: () => {
                      // 深拷贝防止修改影响原数据
                      updateSongModel.value = JSON.parse(JSON.stringify(data));
                      showModal.value = true; // 打开编辑弹窗
                    },
                  },
                  { icon: () => h(NIcon, { component: NotepadEdit20Filled }) }
                ),
              default: () => '修改',
            })
          );
          buttons.push(
            h(NTooltip, null, {
              trigger: () =>
                h( // 使用 NPopconfirm 包裹删除按钮
                  NPopconfirm,
                  { onPositiveClick: () => delSong(data) }, // 确认删除时调用 delSong
                  {
                    trigger: () =>
                      h(
                        NButton,
                        { type: 'error', size: 'small', circle: true },
                        { icon: () => h(NIcon, { component: Delete24Filled }) }
                      ),
                    default: () => `确认删除歌曲《${data.name}》？`, // 确认提示语
                  }
                ),
              default: () => '删除',
            })
          );
        }

        // 4. 额外的按钮 (通过 props 传入)
        if (props.extraButton) {
          buttons.push(...props.extraButton(data));
        }

        // 使用 NSpace 渲染所有按钮
        return h(NSpace, { justify: 'end', size: 8, wrap: false }, () => buttons); // 增加间距，禁止换行
      },
    },
  ]
}

// --- 表单验证规则 ---
const updateSongRules: FormRules = {
  name: [{ required: true, message: '请输入歌曲名称', trigger: ['input', 'blur'] }], // 增加 blur 触发
  // password 规则似乎未使用，注释掉
  // password: [{ required: true, message: '请输入密码' }],
}

// --- 方法 ---

// 监听 props.songs 变化，更新内部列表和列定义
watch(
  () => props.songs,
  (newV) => {
    console.log('Props songs updated, refreshing internal list and columns.'); // 调试信息
    songsInternal.value = [...newV]; // 使用扩展运算符创建新数组，确保响应性
    // 重新生成列定义 (确保筛选选项等是最新的)
    // 使用 nextTick 替代 setTimeout，确保 DOM 更新后再操作
    // nextTick(() => {
    //   columns.value = createColumns();
    // });
    // 实测 watch 触发时直接更新列定义即可，NaiveUI 会处理
    columns.value = createColumns();
  },
  { deep: true } // 深度监听，如果 songs 数组内部对象变化也触发
)

// 更新单首歌曲信息
async function updateSong() {
  try {
    await formRef.value?.validate(); // 触发表单验证
    // 检查是否存在同名歌曲 (排除当前正在编辑的歌曲)
    if (songsInternal.value.some(s => s.name === updateSongModel.value.name && s.key !== updateSongModel.value.key)) {
      message.error('已存在相同名称的歌曲');
      return;
    }
    isLoading.value = true; // 开始加载
    const { code, data, message: errMsg } = await QueryPostAPI<SongsInfo>(SONG_API_URL + 'update', {
      key: updateSongModel.value.key,
      song: updateSongModel.value,
    });
    if (code === 200 && data) {
      const index = songsInternal.value.findIndex((s) => s.key === data.key);
      if (index !== -1) {
        songsInternal.value.splice(index, 1, data); // 更新内部列表数据
      }
      message.success('已更新歌曲信息');
      showModal.value = false; // 关闭弹窗
    } else {
      message.error(`未能更新歌曲信息: ${errMsg || '未知错误'}`);
    }
  } catch (errors) {
    // 表单验证失败
    console.error('Form validation failed:', errors);
    message.warning('请检查表单填写是否正确');
  } finally {
    isLoading.value = false; // 结束加载
  }
}

// 删除单首歌曲
async function delSong(song: SongsInfo) {
  isLoading.value = true; // 开始加载 (虽然删除很快，但保持一致性)
  try {
    const { code, message: errMsg } = await QueryGetAPI<SongsInfo>(SONG_API_URL + 'del', { key: song.key });
    if (code === 200) {
      // 从内部列表中移除
      songsInternal.value = songsInternal.value.filter((s) => s.key !== song.key);
      message.success(`已删除歌曲《${song.name}》`);
      // 如果删除的是正在播放的歌曲，停止播放
      if (playingSong.value?.key === song.key) {
        playingSong.value = undefined;
      }
      // 如果删除的是选中的歌曲，也从选中列表中移除
      selectedColumn.value = selectedColumn.value.filter(key => key !== song.key);
    } else {
      message.error(`未能删除歌曲: ${errMsg || '未知错误'}`);
    }
  } catch (error: any) {
    message.error(`删除歌曲时出错: ${error.message || error}`);
  } finally {
    isLoading.value = false; // 结束加载
  }
}

// 批量删除歌曲
async function delBatchSong() {
  if (selectedColumn.value.length === 0) {
    message.warning('请先选择要删除的歌曲');
    return;
  }
  const ids = selectedColumn.value.map((s) => s.toString());
  isLoading.value = true;
  try {
    const { code, message: errMsg } = await QueryPostAPI<SongsInfo>(SONG_API_URL + 'del-batch', ids);
    if (code === 200) {
      songsInternal.value = songsInternal.value.filter((s) => !ids.includes(s.key));
      message.success(`已删除 ${ids.length} 首歌曲`);
      showBatchModal.value = false; // 关闭批量编辑弹窗
      selectedColumn.value = []; // 清空选择
      // 如果删除的歌曲包含正在播放的歌曲，停止播放
      if (playingSong.value && ids.includes(playingSong.value.key)) {
          playingSong.value = undefined;
      }
    } else {
      message.error(`未能批量删除歌曲: ${errMsg || '未知错误'}`);
    }
  } catch (error: any) {
    message.error(`批量删除歌曲时出错: ${error.message || error}`);
  } finally {
    isLoading.value = false;
  }
}

// --- 批量更新函数 (通用逻辑提取) ---
async function executeBatchUpdate<T>(
    endpoint: string,
    payload: { ids: string[]; data: T },
    updateField: keyof SongsInfo,
    successMessage: string
) {
  if (selectedColumn.value.length === 0) {
    message.warning('请先选择要更新的歌曲');
    return false; // 返回 false 表示未执行
  }
  isLoading.value = true;
  try {
    const { code, message: errMsg } = await QueryPostAPI<SongsInfo[]>(`${SONG_API_URL}${endpoint}`, payload);
    if (code === 200) {
      message.success(successMessage);
      // 更新本地数据
      songsInternal.value.forEach((song, index) => {
        if (payload.ids.includes(song.key)) {
          // 直接修改会破坏响应性，需要创建新对象或使用 Vue.set (或直接修改 ref 的 value)
          // songsInternal.value[index][updateField] = payload.data; // 这种方式可能不触发视图更新
          const updatedSong = { ...songsInternal.value[index], [updateField]: payload.data };
          songsInternal.value.splice(index, 1, updatedSong);
        }
      });
      // 可能需要清空批量编辑表单的值
      return true; // 返回 true 表示成功
    } else {
      message.error(`未能更新歌曲: ${errMsg || '未知错误'}`);
      return false;
    }
  } catch (err: any) {
    message.error(`未能更新歌曲: ${err.message || err}`);
    return false;
  } finally {
    isLoading.value = false;
  }
}

// 批量更新作者
async function batchUpdateAuthor() {
  const success = await executeBatchUpdate(
    'update-batch-author',
    { ids: selectedColumn.value.map(String), data: batchUpdate_Author.value },
    'author',
    `已为 ${selectedColumn.value.length} 首歌曲更新作者`
  );
  if (success) batchUpdate_Author.value = []; // 成功后清空输入
}

// 批量更新标签
async function batchUpdateTag() {
  const success = await executeBatchUpdate(
    'update-batch-tag',
    { ids: selectedColumn.value.map(String), data: batchUpdate_Tag.value },
    'tags',
    `已为 ${selectedColumn.value.length} 首歌曲更新标签`
  );
  if (success) batchUpdate_Tag.value = []; // 成功后清空输入
}

// 批量更新语言
async function batchUpdateLanguage() {
  const success = await executeBatchUpdate(
    'update-batch-language',
    { ids: selectedColumn.value.map(String), data: batchUpdate_Language.value },
    'language',
    `已为 ${selectedColumn.value.length} 首歌曲更新语言`
  );
  if (success) batchUpdate_Language.value = []; // 成功后清空输入
}

// 批量更新点歌选项
async function batchUpdateOption() {
  const success = await executeBatchUpdate(
    'update-batch-option',
    { ids: selectedColumn.value.map(String), data: batchUpdate_Option.value ?? null }, // 如果为 undefined 发送 null
    'options',
    `已为 ${selectedColumn.value.length} 首歌曲更新点歌选项`
  );
   if (success) batchUpdate_Option.value = undefined; // 成功后清空输入
}

// --- 辅助函数 ---

// 根据 SC 价格获取颜色
function GetSCColor(price: number): string {
  if (price <= 0) return `#2a60b2`; // 默认蓝色 (或根据实际需要调整)
  if (price < 30) return `#2a60b2`; // 蓝色
  if (price < 50) return `#2a60b2`; // 蓝色 (合并)
  if (price < 100) return `#427d9e`; // 青色
  if (price < 500) return `#c99801`; // 黄色
  if (price < 1000) return `#e09443`; // 橙色
  if (price < 2000) return `#e54d4d`; // 红色
  return `#ab1a32`; // 深红色 (>= 2000)
}

// 根据大航海等级获取颜色
function GetGuardColor(level: number | null | undefined): string {
  switch (level) {
    case 1: return 'rgb(122, 4, 35)'; // 总督
    case 2: return 'rgb(157, 155, 255)'; // 提督
    case 3: return 'rgb(104, 136, 241)'; // 舰长
    default: return ''; // 默认或无效值
  }
}

// --- 生命周期钩子 ---
onMounted(() => {
  //console.log('Component mounted, initializing...'); // 调试信息
  songsInternal.value = [...props.songs]; // 初始化时复制 props 数据
  // 初始加载列定义
  columns.value = createColumns();
});

</script>

<template>
  <!-- 顶部筛选区域 -->
  <NCard
    embedded
    size="small"
    :bordered="false"
    style="margin-bottom: 10px;"
  >
    <NSpace
      align="center"
      wrap
      item-style="margin-bottom: 5px;"
    >
      <!-- 歌曲名搜索 -->
      <NInput
        v-model:value="searchMusicKeyword"
        placeholder="搜索曲名/译名"
        size="small"
        clearable
        style="min-width: 150px; flex-grow: 1;"
      />
      <!-- 作者筛选 (控制列筛选) -->
      <NSelect
        v-model:value="selectedAuthorFilter"
        placeholder="筛选歌手"
        :options="authorsOptions"
        clearable
        filterable
        size="small"
        style="min-width: 150px; flex-grow: 1;"
      />
      <!-- 语言筛选 (控制 computed 属性) -->
      <NSelect
        v-model:value="selectedLanguageFilter"
        placeholder="筛选语言"
        :options="languageSelectOption"
        multiple
        clearable
        filterable
        size="small"
        style="min-width: 180px; flex-grow: 1;"
        max-tag-count="responsive"
      />
      <!-- 标签筛选 (控制 computed 属性) -->
      <NSelect
        v-model:value="selectedTagFilter"
        placeholder="筛选标签"
        :options="tagsSelectOption"
        multiple
        clearable
        filterable
        size="small"
        style="min-width: 180px; flex-grow: 1;"
        max-tag-count="responsive"
      />
      <!-- 清除作者列筛选按钮 (当顶部选择器清除时，列筛选也应清除，但保留按钮以防万一) -->
      <!-- <NButton
        v-if="authorColumn.filterOptionValue"
        type="warning"
        size="small"
        ghost
        @click="onAuthorClick(authorColumn.filterOptionValue as string)"
      >
        清除歌手列筛选
      </NButton> -->
    </NSpace>
  </NCard>

  <!-- 歌曲数量与批量编辑按钮 -->
  <NSpace
    justify="space-between"
    align="center"
    style="margin-bottom: 5px;"
  >
    <NText depth="3">
      共 {{ songsComputed.length }} / {{ songsInternal.length }} 首
    </NText>
    <!-- 批量编辑按钮 (仅自己的歌单且选中超过1项时显示) -->
    <NButton
      v-if="isSelf"
      :disabled="selectedColumn.length === 0"
      type="primary"
      size="small"
      ghost
      @click="showBatchModal = true"
    >
      批量操作 ({{ selectedColumn.length }})
    </NButton>
  </NSpace>
  <!-- <NDivider style="margin-top: 5px; margin-bottom: 10px;" /> -->

  <!-- 试听播放器区域 -->
  <Transition name="fade">
    <div
      v-if="playingSong"
      style="margin-bottom: 15px;"
    >
      <SongPlayer
        v-model:is-lrc-loading="isLrcLoading"
        :song="playingSong"
        :volume="volume"
        @update:volume="newVol => volume = newVol"
        @close="playingSong = undefined"
      />
      <!-- <NDivider style="margin: 15px 0 0 0;" /> -->
    </div>
  </Transition>

  <!-- 歌曲数据表格 -->
  <NDataTable
    v-model:checked-row-keys="selectedColumn"
    :columns="columns"
    :data="songsComputed"
    size="small"
    :pagination="{
      itemCount: songsInternal.length,
      defaultPageSize: pageSize,
      pageSizes: [10, 25, 50, 100, 200],
      showSizePicker: true,
      showQuickJumper: true,

    }"
    :loading="isLoading && songsComputed.length === 0"
    striped
  />

  <!-- 单个歌曲编辑弹窗 -->
  <NModal
    v-model:show="showModal"
    preset="card"
    style="max-width: 600px;"
    :title="`修改歌曲信息 - ${updateSongModel.name}`"
    :mask-closable="false"
    :closable="true"
  >
    <NForm
      ref="formRef"
      :rules="updateSongRules"
      :model="updateSongModel"
      label-placement="left"
      label-width="auto"
      require-mark-placement="right-hanging"
    >
      <!-- 名称 -->
      <NFormItem
        path="name"
        label="名称"
      >
        <NInput
          v-model:value="updateSongModel.name"
          placeholder="歌曲名称"
          clearable
        />
      </NFormItem>
      <!-- 作者 -->
      <NFormItem
        path="author"
        label="作者"
      >
        <NSelect
          v-model:value="updateSongModel.author"
          :options="authorsOptions"
          placeholder="选择或输入新作者，按回车确认"
          filterable
          multiple
          tag
          clearable
        />
      </NFormItem>
      <!-- 备注 -->
      <NFormItem
        path="description"
        label="备注"
      >
        <NInput
          v-model:value="updateSongModel.description"
          type="textarea"
          placeholder="可选，如歌曲来源、特殊说明等"
          :maxlength="250"
          show-count
          clearable
          autosize
          style="min-width: 300px;"
        />
      </NFormItem>
      <!-- 语言 -->
      <NFormItem
        path="language"
        label="语言"
      >
        <NSelect
          v-model:value="updateSongModel.language"
          :options="languageSelectOption"
          placeholder="选择或输入新语言，按回车确认"
          filterable
          multiple
          tag
          clearable
        />
      </NFormItem>
      <!-- 标签 -->
      <NFormItem
        path="tags"
        label="标签"
      >
        <NSelect
          v-model:value="updateSongModel.tags"
          :options="tagsSelectOption"
          placeholder="选择或输入新标签，按回车确认"
          filterable
          multiple
          tag
          clearable
        />
      </NFormItem>
      <!-- 点歌设置 -->
      <NFormItem path="options">
        <template #label>
          点歌要求
          <NTooltip trigger="hover">
            <template #trigger>
              <NIcon
                :component="Info24Filled"
                style="margin-left: 4px; vertical-align: middle; cursor: help;"
              />
            </template>
            启用后将覆盖全局点歌设置，用于单独设置歌曲要求。不启用则遵循全局设置。
          </NTooltip>
        </template>
        <NSpace vertical>
          <!-- 启用开关 -->
          <NCheckbox
            :checked="updateSongModel.options != null"
            @update:checked="(checked: boolean) => {
              updateSongModel.options = checked ? {
                needJianzhang: false,
                needTidu: false,
                needZongdu: false,
                scMinPrice: undefined,
                fanMedalMinLevel: undefined,
              } : undefined; // 使用 undefined 表示禁用
            }"
          >
            启用独立要求
          </NCheckbox>
          <!-- 详细设置 -->
          <template v-if="updateSongModel.options != null">
            <NSpace>
              <NCheckbox v-model:checked="updateSongModel.options!.needJianzhang">
                舰长
              </NCheckbox>
              <NCheckbox v-model:checked="updateSongModel.options!.needTidu">
                提督
              </NCheckbox>
              <NCheckbox v-model:checked="updateSongModel.options!.needZongdu">
                总督
              </NCheckbox>
            </NSpace>
            <NSpace align="center">
              <NCheckbox
                :checked="updateSongModel.options!.scMinPrice != null"
                @update:checked="(checked: boolean) => updateSongModel.options!.scMinPrice = checked ? 30 : undefined"
              >
                SC点歌
              </NCheckbox>
              <NInputGroup
                v-if="updateSongModel.options!.scMinPrice != null"
                style="width: auto;"
              >
                <NInputGroupLabel size="small">
                  最低
                </NInputGroupLabel>
                <NInputNumber
                  v-model:value="updateSongModel.options!.scMinPrice"
                  :min="1"
                  size="small"
                  style="width: 80px;"
                />
                <NInputGroupLabel size="small">
                  元
                </NInputGroupLabel>
              </NInputGroup>
            </NSpace>
            <NSpace align="center">
              <NCheckbox
                :checked="updateSongModel.options?.fanMedalMinLevel != null"
                @update:checked="(checked: boolean) => {
                  if (updateSongModel.options) {
                    updateSongModel.options.fanMedalMinLevel = checked ? 1 : undefined;
                  }
                }"
              >
                粉丝牌
                <NTooltip trigger="hover">
                  <template #trigger>
                    <NIcon
                      :component="Info24Filled"
                      style="margin-left: 4px; vertical-align: middle; cursor: help;"
                    />
                  </template>
                  启用此项会覆盖全局粉丝牌等级要求。
                </NTooltip>
              </NCheckbox>
              <NInputGroup
                v-if="updateSongModel.options?.fanMedalMinLevel != null"
                style="width: auto;"
              >
                <NInputGroupLabel size="small">
                  最低
                </NInputGroupLabel>
                <NInputNumber
                  v-model:value="updateSongModel.options.fanMedalMinLevel"
                  :min="1"
                  size="small"
                  style="width: 80px;"
                />
                <NInputGroupLabel size="small">
                  级
                </NInputGroupLabel>
              </NInputGroup>
            </NSpace>
          </template>
        </NSpace>
      </NFormItem>
      <!-- 链接 -->
      <NFormItem
        path="url"
        label="链接"
      >
        <NInput
          v-model:value="updateSongModel.url"
          placeholder="可选, 音频链接(mp3/wav/ogg/m4a/flac)可试听"
          clearable
          :disabled="updateSongModel.from !== SongFrom.Custom"
        />
        <NTooltip
          v-if="updateSongModel.from !== SongFrom.Custom"
          trigger="hover"
        >
          <template #trigger>
            <NIcon
              :component="Info24Filled"
              style="margin-left: 8px; cursor: help;"
            />
          </template>
          非自定义来源的歌曲链接通常无法修改。
        </NTooltip>
      </NFormItem>
    </NForm>
    <!-- 底部按钮 -->
    <template #footer>
      <NSpace justify="end">
        <NButton @click="showModal = false">
          取消
        </NButton>
        <NButton
          type="primary"
          :loading="isLoading"
          @click="updateSong"
        >
          确认更新
        </NButton>
      </NSpace>
    </template>
  </NModal>

  <!-- 批量编辑弹窗 -->
  <NModal
    v-model:show="showBatchModal"
    preset="card"
    :title="`批量操作 | 已选择: ${selectedColumn.length} 首`"
    style="max-width: 600px;"
    :mask-closable="false"
  >
    <NTabs
      type="line"
      animated
    >
      <!-- 批量删除 -->
      <NTabPane
        name="delete"
        tab="删除"
      >
        <NText>确定要删除选中的 {{ selectedColumn.length }} 首歌曲吗？此操作不可恢复。</NText>
        <NDivider />
        <NPopconfirm
          :show-icon="false"
          @positive-click="delBatchSong"
        >
          <template #trigger>
            <NButton
              type="error"
              :loading="isLoading"
              :disabled="selectedColumn.length === 0"
            >
              执行删除
            </NButton>
          </template>
          确认执行批量删除操作？
        </NPopconfirm>
      </NTabPane>
      <!-- 批量修改作者 -->
      <NTabPane
        name="author"
        tab="作者"
      >
        <NSelect
          v-model:value="batchUpdate_Author"
          :options="authorsOptions"
          placeholder="选择或输入新作者（将覆盖原有作者）"
          filterable
          multiple
          tag
          clearable
        />
        <NDivider />
        <NButton
          type="primary"
          :loading="isLoading"
          :disabled="selectedColumn.length === 0"
          @click="batchUpdateAuthor"
        >
          更新选中歌曲作者
        </NButton>
      </NTabPane>
      <!-- 批量修改标签 -->
      <NTabPane
        name="tag"
        tab="标签"
      >
        <NSelect
          v-model:value="batchUpdate_Tag"
          :options="tagsSelectOption"
          placeholder="选择或输入新标签（将覆盖原有标签）"
          filterable
          multiple
          tag
          clearable
        />
        <NDivider />
        <NButton
          type="primary"
          :loading="isLoading"
          :disabled="selectedColumn.length === 0"
          @click="batchUpdateTag"
        >
          更新选中歌曲标签
        </NButton>
      </NTabPane>
      <!-- 批量修改语言 -->
      <NTabPane
        name="language"
        tab="语言"
      >
        <NSelect
          v-model:value="batchUpdate_Language"
          :options="languageSelectOption"
          placeholder="选择或输入新语言（将覆盖原有语言）"
          filterable
          multiple
          tag
          clearable
        />
        <NDivider />
        <NButton
          type="primary"
          :loading="isLoading"
          :disabled="selectedColumn.length === 0"
          @click="batchUpdateLanguage"
        >
          更新选中歌曲语言
        </NButton>
      </NTabPane>
      <!-- 批量修改点歌选项 -->
      <NTabPane
        name="option"
        tab="点歌要求"
      >
        <NSpace vertical>
          <NCheckbox
            :checked="batchUpdate_Option != null"
            @update:checked="(checked: boolean) => {
              batchUpdate_Option = checked ? {
                needJianzhang: false,
                needTidu: false,
                needZongdu: false,
                scMinPrice: undefined,
                fanMedalMinLevel: undefined,
              } : undefined;
            }"
          >
            启用/禁用独立要求 (将覆盖原有设置)
          </NCheckbox>
          <template v-if="batchUpdate_Option != null">
            <NSpace>
              <NCheckbox v-model:checked="batchUpdate_Option!.needJianzhang">
                舰长
              </NCheckbox>
              <NCheckbox v-model:checked="batchUpdate_Option!.needTidu">
                提督
              </NCheckbox>
              <NCheckbox v-model:checked="batchUpdate_Option!.needZongdu">
                总督
              </NCheckbox>
            </NSpace>
            <NSpace align="center">
              <NCheckbox
                :checked="batchUpdate_Option!.scMinPrice != null"
                @update:checked="(checked: boolean) => batchUpdate_Option!.scMinPrice = checked ? 30 : undefined"
              >
                SC点歌
              </NCheckbox>
              <NInputGroup
                v-if="batchUpdate_Option!.scMinPrice != null"
                style="width: auto;"
              >
                <NInputGroupLabel size="small">
                  最低
                </NInputGroupLabel>
                <NInputNumber
                  v-model:value="batchUpdate_Option!.scMinPrice"
                  :min="1"
                  size="small"
                  style="width: 80px;"
                />
                <NInputGroupLabel size="small">
                  元
                </NInputGroupLabel>
              </NInputGroup>
            </NSpace>
            <NSpace align="center">
              <NCheckbox
                :checked="batchUpdate_Option!.fanMedalMinLevel != null"
                @update:checked="(checked: boolean) => batchUpdate_Option!.fanMedalMinLevel = checked ? 1 : undefined"
              >
                粉丝牌
              </NCheckbox>
              <NInputGroup
                v-if="batchUpdate_Option!.fanMedalMinLevel != null"
                style="width: auto;"
              >
                <NInputGroupLabel size="small">
                  最低
                </NInputGroupLabel>
                <NInputNumber
                  v-model:value="batchUpdate_Option!.fanMedalMinLevel"
                  :min="1"
                  size="small"
                  style="width: 80px;"
                />
                <NInputGroupLabel size="small">
                  级
                </NInputGroupLabel>
              </NInputGroup>
            </NSpace>
          </template>
        </NSpace>
        <NDivider />
        <NButton
          type="primary"
          :loading="isLoading"
          :disabled="selectedColumn.length === 0"
          @click="batchUpdateOption"
        >
          更新选中歌曲要求
        </NButton>
      </NTabPane>
    </NTabs>
  </NModal>
</template>

<style scoped>
/* 淡入淡出动画 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* 优化 NDataTable 高度适应 */
/* :deep(.n-data-table .n-data-table-base-table) { */
  /* display: flex; */
  /* flex-direction: column; */
/* } */
/* :deep(.n-data-table .n-data-table-base-table-body) { */
  /* flex: 1; */
/* } */

/* Naive UI 默认样式可能已足够，若需要强制滚动条可取消注释 */
/* :deep(.n-data-table-wrapper) {
    overflow: auto;
} */

/* 移除NCard默认边框，如果全局设置了 */
.n-card {
  border: none !important;
}
</style>

<style>
/* 全局样式 (如果需要影响 GetPlayButton 内部的 SVG) */
.netease path:nth-child(2) {
  fill: #c20c0c; /* 网易云红色 */
}

.fivesing path:first-child { /* 调整选择器以匹配 GetPlayButton 生成的 SVG 结构 */
  fill: #00bbb3; /* 5sing 绿色 */
}
.bilibili path {
    fill: #00a1d6; /* B站蓝色 */
}
/* 可以为其他来源添加类似样式 */
</style>