import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:unionapp/pages/music/score_single.dart';
import '../../../model/song_model.dart';
import '../../../providers/user_provider.dart';
import '../../../service/song_service.dart';
import '../../../service/user_service.dart';
import '../../tool/cacheImage.dart';

class MusicPage extends StatefulWidget {
  const MusicPage({super.key});

  @override
  State<MusicPage> createState() => _MusicPageState();
}

class _MusicPageState extends State<MusicPage> with SingleTickerProviderStateMixin {
  bool _isLoading = true;
  bool _isRefreshing = false;
  String _errorMessage = '';

  List<SongModel> _allSongs = [];
  List<SongModel> _displaySongs = [];

  // 筛选
  String _searchQuery = '';
  int? _filterLevelType;

  // --- 修改点 1: 将单选 String? 改为多选 Set<String> ---
  Set<String> _filterVersions = {};
  Set<String> _filterGenres = {};

  double? _selectedMinLevel;
  double? _selectedMaxLevel;
  bool _isAdvancedFilterExpanded = false;

  late AnimationController _animationController;
  late Animation<double> _animation;

  static const List<double> _levelOptions = [
    1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5,
    6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5,
    11.0, 11.5, 12.0, 12.5,
    13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9,
    14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9,
    15.0,
  ];

  late FixedExtentScrollController _minLevelScrollController;
  late FixedExtentScrollController _maxLevelScrollController;
  Set<String> _availableVersions = {};
  Set<String> _availableGenres = {};

  // 用户成绩缓存：key = 真实完整 musicId
  Map<int, Map<int, dynamic>> _userScoreCache = {};

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
    _animation = CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    );

    _minLevelScrollController = FixedExtentScrollController(initialItem: 0);
    _maxLevelScrollController = FixedExtentScrollController(initialItem: _levelOptions.length - 1);

    _loadAllSongs();
    _loadUserScores();

    UserProvider.instance.addListener(_onUserChanged);
  }

  void _onUserChanged() {
    if (mounted) {
      _loadUserScores();
    }
  }

  @override
  void dispose() {
    UserProvider.instance.removeListener(_onUserChanged);
    _animationController.dispose();
    _minLevelScrollController.dispose();
    _maxLevelScrollController.dispose();
    super.dispose();
  }

  // 加载所有歌曲
  Future<void> _loadAllSongs() async {
    setState(() => _isLoading = true);
    try {
      final songs = await SongService.getAllSongs();
      _allSongs = songs;
      final uniqueSongs = <int, SongModel>{};
      for (final song in songs) {
        uniqueSongs.putIfAbsent(song.id, () => song);
      }
      _allSongs = uniqueSongs.values.toList();
      _allSongs.sort((a, b) => (b.players ?? 0).compareTo(a.players ?? 0));
      _displaySongs = List.from(_allSongs);

      // 更新可用选项
      _availableVersions = songs.map((s) => s.from).where((v) => v.isNotEmpty).toSet();
      _availableGenres = songs.map((s) => s.genre).where((g) => g.isNotEmpty).toSet();

      setState(() => _errorMessage = '');
    } catch (e) {
      setState(() => _errorMessage = e.toString());
    } finally {
      setState(() => _isLoading = false);
    }
  }

  // 加载用户成绩
  Future<void> _loadUserScores() async {
    try {
      final userProvider = UserProvider.instance;
      final token = userProvider.token;
      if (token == null) return;

      final userName = userProvider.selectedCnUserName;
      Map<String, dynamic> scoreData;

      if (userProvider.scoreDataSource == 'sega') {
        final segaId = userProvider.selectedSegaId;
        if (segaId == null || segaId.isEmpty) return;
        scoreData = await UserService.getSegaRatingData(token, segaId);
      } else {
        scoreData = await SongService.getUserAllScores(token, name: userName);
      }

      List<dynamic> userMusicList = [];

      if (scoreData.containsKey('userScoreAll_')) {
        userMusicList = scoreData['userScoreAll_']['userMusicList'] ?? [];
      } else if (scoreData.containsKey('userMusicList')) {
        userMusicList = scoreData['userMusicList'] ?? [];
      } else if (scoreData.containsKey('segaId2chartlist')) {
        final segaId = userProvider.selectedSegaId;
        final map = scoreData['segaId2chartlist'] ?? {};
        userMusicList = (map[segaId] as List?) ?? [];
      }

      _userScoreCache.clear();
      for (var group in userMusicList) {
        final details = group['userMusicDetailList'] ?? [];
        for (var d in details) {
          int realMusicId = d['musicId']; // 完整ID
          int level = d['level'] ?? 0;
          _userScoreCache[realMusicId] ??= {};
          _userScoreCache[realMusicId]![level] = d;
        }
      }
      setState(() {});
    } catch (e) {
      print("加载成绩失败: $e");
    }
  }

  // 搜索 + 过滤
  void _applyFilters() {
    final q = _normalizeSearch(_searchQuery);
    _displaySongs = _allSongs.where((song) {
      if (q.isNotEmpty) {
        bool match = false;
        if (_normalizeSearch(song.title).contains(q)) match = true;
        if (_normalizeSearch(song.artist).contains(q)) match = true;
        if (song.id.toString().contains(q)) match = true;
        for (var a in song.albums) {
          if (_normalizeSearch(a).contains(q)) match = true;
        }
        if (!match) return false;
      }

      // --- 修改点 2: 多选过滤逻辑 ---
      // 如果选择了版本，歌曲版本必须在选中集合中
      if (_filterVersions.isNotEmpty && !_filterVersions.contains(song.from)) return false;

      // 如果选择了流派，歌曲流派必须在选中集合中
      if (_filterGenres.isNotEmpty && !_filterGenres.contains(song.genre)) return false;

      if (_filterLevelType != null) {
        bool hasLevel = false;
        final allDiffs = _getAllDifficultiesWithType(song);
        for (var d in allDiffs) {
          if (d['diff']['level_id'] == _filterLevelType) {
            hasLevel = true;
            break;
          }
        }
        if (!hasLevel) return false;
      }

      if (_selectedMinLevel != null || _selectedMaxLevel != null) {
        bool inRange = false;
        final allDiffs = _getAllDifficultiesWithType(song);
        for (var d in allDiffs) {
          final lv = double.tryParse(d['diff']['level_value']?.toString() ?? '');
          if (lv == null) continue;
          final minOk = _selectedMinLevel == null || lv >= _selectedMinLevel!;
          final maxOk = _selectedMaxLevel == null || lv <= _selectedMaxLevel!;
          if (minOk && maxOk) {
            inRange = true;
            break;
          }
        }
        if (!inRange) return false;
      }

      return true;
    }).toList();
    setState(() {});
  }

  String _normalizeSearch(String? s) {
    if (s == null) return '';
    return s.trim().toLowerCase();
  }

  // 带类型的难度（SD/DX/UT）
  List<Map<String, dynamic>> _getAllDifficultiesWithType(SongModel song) {
    List<Map<String, dynamic>> all = [];
    if (song.sd != null && song.sd!.isNotEmpty) {
      for (var d in song.sd!.values) {
        all.add({'type': 'SD', 'diff': d});
      }
    }
    if (song.dx != null && song.dx!.isNotEmpty) {
      for (var d in song.dx!.values) {
        all.add({'type': 'DX', 'diff': d});
      }
    }
    if (song.ut != null && song.ut!.isNotEmpty) {
      for (var d in song.ut!.values) {
        all.add({'type': 'UT', 'diff': d});
      }
    }
    return all;
  }

  // 根据歌曲类型获取真实完整ID
  int _getRealMusicId(SongModel song, String type) {
    if (type == "SD") {
      return song.id;
    } else if (type == "DX") {
      return 10000 + song.id;
    } else {
      return 100000 + song.id;
    }
  }

  void _resetFilters() {
    setState(() {
      _searchQuery = '';
      _filterLevelType = null;
      _filterVersions.clear(); // 清空集合
      _filterGenres.clear();   // 清空集合
      _selectedMinLevel = null;
      _selectedMaxLevel = null;
    });
    _minLevelScrollController.jumpToItem(0);
    _maxLevelScrollController.jumpToItem(_levelOptions.length - 1);
    _applyFilters();
  }

  String _getLevelRangeText() {
    if (_selectedMinLevel == null && _selectedMaxLevel == null) return "全部";
    final min = _selectedMinLevel?.toStringAsFixed(1) ?? "1.0";
    final max = _selectedMaxLevel?.toStringAsFixed(1) ?? "15.0";
    return "$min ~ $max";
  }

  void _showLevelPickerDialog() {
    int minIdx = _selectedMinLevel != null ? _levelOptions.indexOf(_selectedMinLevel!) : 0;
    int maxIdx = _selectedMaxLevel != null ? _levelOptions.indexOf(_selectedMaxLevel!) : _levelOptions.length - 1;

    showModalBottomSheet(
      context: context,
      shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
      builder: (context) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          _minLevelScrollController.jumpToItem(minIdx);
          _maxLevelScrollController.jumpToItem(maxIdx);
        });

        return Container(
          height: 300,
          padding: const EdgeInsets.only(top: 16),
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    TextButton(
                      onPressed: () {
                        setState(() {
                          _selectedMinLevel = null;
                          _selectedMaxLevel = null;
                        });
                        Navigator.pop(context);
                      },
                      child: const Text("重置", style: TextStyle(color: Colors.red)),
                    ),
                    const Text("定数范围", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
                    TextButton(
                      onPressed: () {
                        final min = _levelOptions[_minLevelScrollController.selectedItem];
                        final max = _levelOptions[_maxLevelScrollController.selectedItem];
                        setState(() {
                          _selectedMinLevel = min;
                          _selectedMaxLevel = max;
                          _applyFilters();
                        });
                        Navigator.pop(context);
                      },
                      child: const Text("确定", style: TextStyle(fontWeight: FontWeight.bold)),
                    ),
                  ],
                ),
              ),
              const Divider(),
              Expanded(
                child: Row(
                  children: [
                    Expanded(
                      child: Column(
                        children: [
                          const Text("最小定数", style: TextStyle(fontSize: 12, color: Colors.grey)),
                          Expanded(
                            child: CupertinoPicker(
                              scrollController: _minLevelScrollController,
                              itemExtent: 40,
                              onSelectedItemChanged: (_) {},
                              children: _levelOptions.map((e) => Center(child: Text(e.toStringAsFixed(1)))).toList(),
                            ),
                          ),
                        ],
                      ),
                    ),
                    Expanded(
                      child: Column(
                        children: [
                          const Text("最大定数", style: TextStyle(fontSize: 12, color: Colors.grey)),
                          Expanded(
                            child: CupertinoPicker(
                              scrollController: _maxLevelScrollController,
                              itemExtent: 40,
                              onSelectedItemChanged: (_) {},
                              children: _levelOptions.map((e) => Center(child: Text(e.toStringAsFixed(1)))).toList(),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  // --- 新增：多选 Chip 构建器 ---
  Widget _buildMultiSelectChip({
    required String label,
    required Set<String> selectedValues,
    required Set<String> allOptions,
    required Function(Set<String>) onSelectionChanged,
  }) {
    return InkWell(
      onTap: () {
        _showMultiSelectDialog(
          context,
          title: label,
          allOptions: allOptions.toList()..sort(),
          selectedValues: selectedValues,
          onConfirm: (newSelection) {
            setState(() {
              onSelectionChanged(newSelection);
            });
            _applyFilters();
          },
        );
      },
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey.shade400),
          borderRadius: BorderRadius.circular(4),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
            Flexible(
              child: Text(
                selectedValues.isEmpty ? "全部" : "已选 ${selectedValues.length}",
                style: TextStyle(color: Colors.grey[600], fontSize: 12),
                overflow: TextOverflow.ellipsis,
              ),
            ),
            const Icon(Icons.arrow_drop_down, color: Colors.grey),
          ],
        ),
      ),
    );
  }

  void _showMultiSelectDialog(
      BuildContext context, {
        required String title,
        required List<String> allOptions,
        required Set<String> selectedValues,
        required Function(Set<String>) onConfirm,
      }) {
    // 临时存储选择状态
    final tempSelection = Set<String>.from(selectedValues);

    showDialog(
      context: context,
      builder: (ctx) {
        return StatefulBuilder(
          builder: (context, setDialogState) {
            return AlertDialog(
              title: Text(title),
              content: SizedBox(
                width: double.maxFinite,
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: allOptions.length,
                  itemBuilder: (context, index) {
                    final option = allOptions[index];
                    final isSelected = tempSelection.contains(option);
                    return CheckboxListTile(
                      title: Text(option),
                      value: isSelected,
                      onChanged: (bool? value) {
                        setDialogState(() {
                          if (value == true) {
                            tempSelection.add(option);
                          } else {
                            tempSelection.remove(option);
                          }
                        });
                      },
                      controlAffinity: ListTileControlAffinity.leading,
                      dense: true,
                    );
                  },
                ),
              ),
              actions: [
                TextButton(
                  onPressed: () {
                    setDialogState(() {
                      tempSelection.clear();
                    });
                  },
                  child: const Text("清空"),
                ),
                TextButton(
                  onPressed: () => Navigator.pop(ctx),
                  child: const Text("取消"),
                ),
                ElevatedButton(
                  onPressed: () {
                    onConfirm(tempSelection);
                    Navigator.pop(ctx);
                  },
                  child: const Text("确定"),
                ),
              ],
            );
          },
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("歌曲列表"),
        actions: [
          if (_isRefreshing)
            const Padding(
              padding: EdgeInsets.all(8.0),
              child: SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2)),
            )
          else
            IconButton(icon: const Icon(Icons.refresh), onPressed: () async {
              setState(() => _isRefreshing = true);
              await _loadAllSongs();
              await _loadUserScores();
              setState(() => _isRefreshing = false);
            })
        ],
      ),
      body: Column(
        children: [
          _buildFilterBar(),
          Expanded(child: _buildBody()),
        ],
      ),
    );
  }

  Widget _buildFilterBar() {
    return Container(
      color: Theme.of(context).cardColor,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    decoration: InputDecoration(
                      hintText: "搜索歌名/别名/艺术家/ID",
                      prefixIcon: const Icon(Icons.search),
                      border: OutlineInputBorder(borderRadius: BorderRadius.circular(25)),
                      contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 16),
                      isDense: true,
                    ),
                    onChanged: (v) {
                      setState(() => _searchQuery = v);
                      _applyFilters();
                    },
                  ),
                ),
                IconButton(
                  icon: Icon(_isAdvancedFilterExpanded ? Icons.expand_less : Icons.expand_more),
                  onPressed: () {
                    setState(() {
                      _isAdvancedFilterExpanded = !_isAdvancedFilterExpanded;
                      _isAdvancedFilterExpanded ? _animationController.forward() : _animationController.reverse();
                    });
                  },
                ),
                if (_hasFilters())
                  IconButton(icon: const Icon(Icons.clear, color: Colors.redAccent), onPressed: _resetFilters),
              ],
            ),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
            child: Row(
              children: [
                Expanded(
                  child: _buildDropdown(
                    label: "难度类型",
                    value: _filterLevelType,
                    items: const [
                      DropdownMenuItem(value: null, child: Text("全部")),
                      DropdownMenuItem(value: 0, child: Text("Basic")),
                      DropdownMenuItem(value: 1, child: Text("Advanced")),
                      DropdownMenuItem(value: 2, child: Text("Expert")),
                      DropdownMenuItem(value: 3, child: Text("Master")),
                      DropdownMenuItem(value: 4, child: Text("Re:Master")),
                    ],
                    onChanged: (v) {
                      setState(() => _filterLevelType = v);
                      _applyFilters();
                    },
                  ),
                ),
              ],
            ),
          ),
          SizeTransition(
            sizeFactor: _animation,
            axisAlignment: -1,
            child: Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(color: Colors.grey.withAlpha(20), border: Border(top: BorderSide(color: Colors.grey.shade300))),
              child: Column(
                children: [
                  // --- 修改点 3: UI 替换为多选 Chip ---
                  Row(
                    children: [
                      Expanded(
                        child: _buildMultiSelectChip(
                          label: "版本",
                          selectedValues: _filterVersions,
                          allOptions: _availableVersions,
                          onSelectionChanged: (newSet) {
                            _filterVersions = newSet;
                          },
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: _buildMultiSelectChip(
                          label: "流派",
                          selectedValues: _filterGenres,
                          allOptions: _availableGenres,
                          onSelectionChanged: (newSet) {
                            _filterGenres = newSet;
                          },
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 8),
                  InkWell(
                    onTap: _showLevelPickerDialog,
                    child: Container(
                      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
                      decoration: BoxDecoration(border: Border.all(color: Colors.grey.shade400), borderRadius: BorderRadius.circular(4)),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          const Text("定数范围", style: TextStyle(fontWeight: FontWeight.bold)),
                          Text(_getLevelRangeText(), style: TextStyle(color: Colors.grey[600])),
                          const Icon(Icons.arrow_drop_down, color: Colors.grey),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  String getLeftEllipsisText(String text, int maxLength) {
    if (text.length <= maxLength) return text;
    return '...${text.substring(text.length - maxLength + 3)}'; // +3 是因为 "..." 占3个字符
  }

  Widget _buildDropdown({required String label, required dynamic value, required List<DropdownMenuItem> items, required ValueChanged onChanged}) {
    return DropdownButtonFormField(
      value: value,
      isExpanded: true,
      decoration: InputDecoration(labelText: label, border: const OutlineInputBorder(), contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), isDense: false),
      items: items,
      onChanged: onChanged,
    );
  }

  bool _hasFilters() =>
      _searchQuery.isNotEmpty ||
          _filterLevelType != null ||
          _filterVersions.isNotEmpty || // 修改判断逻辑
          _filterGenres.isNotEmpty ||   // 修改判断逻辑
          _selectedMinLevel != null ||
          _selectedMaxLevel != null;

  Widget _buildBody() {
    if (_isLoading) return const Center(child: CircularProgressIndicator());
    if (_errorMessage.isNotEmpty) return Center(child: Text(_errorMessage, style: const TextStyle(color: Colors.red)));
    if (_displaySongs.isEmpty) return const Center(child: Text("无匹配歌曲"));

    return ListView.builder(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
      itemCount: _displaySongs.length,
      itemBuilder: (_, idx) {
        final song = _displaySongs[idx];
        return _songItem(song);
      },
    );
  }

  Widget _songItem(SongModel song) {
    final cover = _getCoverUrl(song.id);
    bool hasScore = false;

    // 检查SD/DX/UT任意一个有成绩
    if (song.sd != null && _userScoreCache.containsKey(song.id)) hasScore = true;
    if (song.dx != null && _userScoreCache.containsKey(10000 + song.id)) hasScore = true;
    if (song.ut != null && _userScoreCache.containsKey(100000 + song.id)) hasScore = true;

    // --- 新增：处理别名逻辑 ---
    List<String> rawAliases = song.albums ?? [];
    final seen = <String>{};
    final uniqueAliases = rawAliases.where((alias) => seen.add(alias)).toList();
    final filteredAliases = uniqueAliases.where((alias) =>
    alias != song.title &&
        alias != song.artist
    ).toList();

    String aliasDisplayText = "";
    if (filteredAliases.isNotEmpty) {
      int maxAliasCount = 6;
      List<String> displayList = filteredAliases.take(maxAliasCount).toList();
      aliasDisplayText = displayList.join(" · ");
      if (filteredAliases.length > maxAliasCount) {
        aliasDisplayText += " ...";
      }
    }
    // -------------------------

    return Card(
      margin: const EdgeInsets.only(bottom: 10),
      elevation: 4,
      shadowColor: Colors.purpleAccent.withOpacity(0.5),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      child: InkWell(
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (_) => SongDetailPage(
              song: song,
              userScoreCache: _userScoreCache,
            )),
          );
        },
        borderRadius: BorderRadius.circular(12),
        child: Padding(
          padding: const EdgeInsets.all(12),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 左侧：封面 + ID 区域
              Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  ClipRRect(
                    borderRadius: BorderRadius.circular(2),
                    child: CacheImage.network(
                      cover,
                      width: 100,
                      height: 100,
                      fit: BoxFit.cover,
                      errorBuilder: (_, __, ___) => Container(
                        width: 60,
                        height: 60,
                        color: Colors.grey[200],
                        child: const Icon(Icons.music_note),
                      ),
                    ),
                  ),
                  const SizedBox(height: 2),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      if (song.cn == true)
                        _buildTag(
                          "CN",
                          backgroundColor: Colors.redAccent,
                          shadowColor: Colors.red.withOpacity(0.3),
                        ),
                      if (song.jp == true)
                        _buildTag(
                          "JP",
                          backgroundColor: Colors.blueAccent,
                          shadowColor: Colors.red.withOpacity(0.3),
                        ),
                      if (song.m2l == true)
                        _buildTag(
                          "M2L",
                          gradient: const LinearGradient(
                            colors: [Colors.purple, Colors.blueAccent],
                            begin: Alignment.centerLeft,
                            end: Alignment.centerRight,
                          ),
                        ),
                      if (song.long == true)
                        _buildTag(
                          "LONG",
                          gradient: const LinearGradient(
                            colors: [Colors.black12, Colors.lightBlueAccent],
                            begin: Alignment.topRight,
                            end: Alignment.bottomLeft,
                          ),

                        ),
                      Text(
                        " ${song.id}",
                        style: const TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: 11,
                        ),
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ],
                  ),
                  SizedBox(
                    width: 100,
                    child: Text(
                      getLeftEllipsisText("${song.from}", 15),
                      style: const TextStyle(
                        fontSize: 9,
                        color: Colors.grey,
                      ),
                      maxLines: 1,
                      textAlign: TextAlign.right,
                      overflow: TextOverflow.visible,
                    ),
                  )
                ],
              ),
              const SizedBox(width: 12),

              // 右侧：详细信息
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text(
                      song.title,
                      style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                    const SizedBox(height: 4),
                    Text(
                      song.artist ?? "Unknown",
                      style: TextStyle(fontSize: 12, color: Colors.grey[600]),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                    const SizedBox(height: 6),
                    ..._getDifficultyChipsByType(song),
                    if (aliasDisplayText.isNotEmpty) ...[
                      const SizedBox(height: 6),
                      LayoutBuilder(
                        builder: (context, constraints) {
                          return Text(
                            aliasDisplayText,
                            style: TextStyle(
                              fontSize: 10,
                              color: Colors.grey[500],
                              height: 1.2,
                            ),
                            maxLines: 5,
                            overflow: TextOverflow.ellipsis,
                          );
                        },
                      ),
                    ],
                  ],
                ),
              ),

              if (hasScore)
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
                  decoration: BoxDecoration(color: Colors.greenAccent.withOpacity(0.15), borderRadius: BorderRadius.circular(4)),
                  child: const Text("Score", style: TextStyle(color: Colors.green, fontSize: 12, fontWeight: FontWeight.bold)),
                ),
            ],
          ),
        ),
      ),
    );
  }
  Widget _buildTag(
      String text, {
        Color? backgroundColor,
        Gradient? gradient,
        Color? shadowColor,
        double shadowBlurRadius = 2,
        Offset shadowOffset = const Offset(0, 1),
        double borderRadius = 2,
        double fontSize = 8,
        Color textColor = Colors.white,
      }) {
    return Container(
      margin: const EdgeInsets.only(right: 3),
      padding: const EdgeInsets.symmetric(horizontal: 3, vertical: 1),
      decoration: BoxDecoration(
        color: gradient == null ? (backgroundColor ?? Colors.blueAccent) : null,
        gradient: gradient,
        borderRadius: BorderRadius.circular(borderRadius),
        boxShadow: shadowColor != null
            ? [
          BoxShadow(
            color: shadowColor,
            blurRadius: shadowBlurRadius,
            offset: shadowOffset,
          )
        ]
            : null,
      ),
      child: Text(
        text,
        style: TextStyle(
          color: textColor,
          fontSize: fontSize,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
  List<Widget> _getDifficultyChipsByType(SongModel song) {
    final diffs = _getAllDifficultiesWithType(song);
    final Map<String, List<dynamic>> typeGroups = {};
    for (var item in diffs) {
      final type = item['type'] as String;
      typeGroups.putIfAbsent(type, () => []);
      typeGroups[type]!.add(item);
    }

    final order = ['SD', 'DX', 'UT'];
    List<Widget> rows = [];

    for (final type in order) {
      final items = typeGroups[type];
      if (items == null || items.isEmpty) continue;

      final row = Wrap(
        spacing: 6,
        runSpacing: 4,
        children: items.map<Widget>((item) {
          final diff = item['diff'] as Map;
          final lid = diff['level_id'] as int;
          final lvValue = double.tryParse(diff['level_value']?.toString() ?? '') ?? 0;

          bool isBanquet = lvValue == 10.0 || song.id > 100000 || type == 'UT';
          int realId = _getRealMusicId(song, type);
          bool hasScore = _userScoreCache[realId]?[lid] != null;

          Color color = Colors.grey;
          String label = "";

          if (isBanquet) {
            color = Colors.pinkAccent;
            if (type == 'UT') {
              final utTitleMap = song.utTitle as Map?;
              if (utTitleMap != null && utTitleMap.isNotEmpty) {
                final key = item["diff"]['id'].toString();
                if (utTitleMap.containsKey(key)) {
                  label = utTitleMap[key].toString();
                } else {
                  label = "UT";
                }
              } else {
                label = "UT";
              }
            } else {
              label = type;
            }
          } else {
            switch (lid) {
              case 0:
                color = Colors.green;
                label = type;
                break;
              case 1:
                color = Colors.yellow.shade700;
                label = type;
                break;
              case 2:
                color = Colors.red;
                label = type;
                break;
              case 3:
                color = Colors.purple;
                label = type;
                break;
              case 4:
                color = Colors.purpleAccent.shade100;
                label = type;
                break;
              default:
                return const SizedBox();
            }
          }

          return Container(
            padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 1),
            decoration: BoxDecoration(
              color: color.withOpacity(hasScore ? 0.25 : 0.1),
              borderRadius: BorderRadius.circular(4),
              border: Border.all(color: color.withOpacity(0.5)),
            ),
            child: Text(
              isBanquet ? label : "$label ${lvValue.toStringAsFixed(1)}",
              style: TextStyle(
                color: color,
                fontSize: 9,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      );

      rows.add(row);
      rows.add(const SizedBox(height: 4));
    }

    return rows;
  }

  String _getCoverUrl(int musicId) {
    int displayId = musicId % 10000;
    if (musicId >= 16000 && musicId <= 20000) {
      String idStr = displayId.toString().padLeft(6, '0');
      return "https://u.mai2.link/jacket/UI_Jacket_$idStr.jpg";
    } else {
      return "https://cdn.godserver.cn/resource/static/mai/cover/$displayId.png";
    }
  }
}