import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';
import 'package:webview_flutter/webview_flutter.dart'; // 【新增】导入 webview
import '../../../model/song_model.dart';
import '../../../providers/user_provider.dart';
import '../../../service/song_service.dart';
import '../../../service/user_service.dart';
import '../../../widgets/score_progress_chart.dart';
import '../../tool/cacheImage.dart';
import '../../tool/gradientText.dart';

class SongDetailPage extends StatefulWidget {
  final SongModel song;
  final Map<int, Map<int, dynamic>> userScoreCache;

  const SongDetailPage({
    super.key,
    required this.song,
    required this.userScoreCache,
  });

  @override
  State<SongDetailPage> createState() => _SongDetailPageState();
}

class _SongDetailPageState extends State<SongDetailPage> {
  String? _selectedType;
  bool _isAliasExpanded = false;
  bool _isDownloading = false;

  final Map<String, List<Map<String, dynamic>>> _chartDataCache = {};
  final Map<String, bool> _isLoadingChart = {};

  // 【新增】用于控制 WebView 显示和加载 URL
  String? _previewUrl;
  late WebViewController _webViewController;

  @override
  void initState() {
    super.initState();
    _initSelectedType();

    // 【新增】初始化 WebViewController
    _webViewController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            // 可选：更新加载进度
          },
          onPageStarted: (String url) {},
          onPageFinished: (String url) {},
          onHttpError: (HttpResponseError error) {},
          onWebResourceError: (WebResourceError error) {},
        ),
      );
  }

  void _initSelectedType() {
    if (widget.song.sd != null && widget.song.sd!.isNotEmpty) {
      _selectedType = 'SD';
    } else if (widget.song.dx != null && widget.song.dx!.isNotEmpty) {
      _selectedType = 'DX';
    } else if (widget.song.ut != null && widget.song.ut!.isNotEmpty) {
      _selectedType = 'UT';
    }
  }

  List<String> _getAvailableTypes() {
    List<String> types = [];
    if (widget.song.sd != null && widget.song.sd!.isNotEmpty) types.add('SD');
    if (widget.song.dx != null && widget.song.dx!.isNotEmpty) types.add('DX');
    if (widget.song.ut != null && widget.song.ut!.isNotEmpty) types.add('UT');
    return types;
  }

  List<Map<String, dynamic>> _getCurrentDifficulties() {
    List<Map<String, dynamic>> all = [];
    if (_selectedType == 'SD' && widget.song.sd != null) {
      for (var d in widget.song.sd!.values) {
        all.add({'type': 'SD', 'diff': d});
      }
    } else if (_selectedType == 'DX' && widget.song.dx != null) {
      for (var d in widget.song.dx!.values) {
        all.add({'type': 'DX', 'diff': d});
      }
    } else if (_selectedType == 'UT' && widget.song.ut != null) {
      for (var d in widget.song.ut!.values) {
        all.add({'type': 'UT', 'diff': d});
      }
    }
    all.sort((a, b) {
      int idA = a['diff']['level_id'] ?? 0;
      int idB = b['diff']['level_id'] ?? 0;
      return idA.compareTo(idB);
    });
    return all;
  }

  Future<void> _downloadCurrentTypeAdx() async {
    if (_isDownloading) return;
    if (_selectedType == null || _selectedType == 'UT') {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text("仅支持下载 SD 或 DX 谱面")),
      );
      return;
    }

    setState(() {
      _isDownloading = true;
    });

    try {
      int songId = widget.song.id;
      String url;
      String type = _selectedType!;

      if (type == 'SD') {
        String idStr = songId.toString();
        url = "https://cdn.godserver.cn/resource/static/adx/$idStr.adx";
      } else {
        int dxId = songId + 10000;
        String idStr = dxId.toString();
        url = "https://cdn.godserver.cn/resource/static/adx/$idStr.adx";
      }

      final response = await http.get(Uri.parse(url));
      if (response.statusCode != 200) {
        throw Exception("下载失败: HTTP ${response.statusCode}");
      }

      final directory = await getApplicationDocumentsDirectory();
      String safeTitle = widget.song.title?.replaceAll(RegExp(r'[^\w\s\u4e00-\u9fa5]'), '_') ?? "song";
      String fileName = "${safeTitle}_$type.adx";
      final filePath = "${directory.path}/$fileName";
      final file = File(filePath);

      await file.writeAsBytes(response.bodyBytes);
      final result = await OpenFile.open(filePath);

      if (result.type != ResultType.done) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text("无法打开文件: ${result.message}")),
        );
      }

    } catch (e) {
      print("Download error: $e");
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("下载出错: $e")),
      );
    } finally {
      setState(() {
        _isDownloading = false;
      });
    }
  }

  // 【新增】加载图表数据逻辑保持不变...
  Future<void> _loadTypeChartData(String type) async {
    if (_chartDataCache.containsKey(type) || _isLoadingChart[type] == true) {
      return;
    }
    setState(() {
      _isLoadingChart[type] = true;
    });
    try {
      final userProvider = UserProvider.instance;
      final token = userProvider.token;
      if (token == null || token.isEmpty) {
        setState(() => _isLoadingChart[type] = false);
        return;
      }
      int apiMusicId;
      if (type == 'SD') {
        apiMusicId = widget.song.id;
      } else if (type == 'DX') {
        apiMusicId = 10000 + widget.song.id;
      } else {
        setState(() => _isLoadingChart[type] = false);
        return;
      }
      final logs = await UserService.getChartLog(token, [apiMusicId]);
      logs.sort((a, b) => a.time.compareTo(b.time));
      final chartList = logs.map((log) => {
        'achievement': log.segaChartNew?.achievement ?? 0,
        'time': log.time,
        'scoreRank': log.segaChartNew?.scoreRank ?? 0,
        'comboStatus': log.segaChartNew?.comboStatus ?? 0,
        'syncStatus': log.segaChartNew?.syncStatus ?? 0,
        'deluxscoreMax': log.segaChartNew?.deluxscoreMax ?? 0,
        'playCount': log.segaChartNew?.playCount ?? 0,
        'level': log.segaChartNew?.level ?? 0,
      }).toList();
      setState(() {
        _chartDataCache[type] = chartList;
        _isLoadingChart[type] = false;
      });
    } catch (e) {
      print("Load chart error: $e");
      setState(() => _isLoadingChart[type] = false);
    }
  }

  Future<void> _loadUtChartData(String cacheKey, int realId) async {
    if (_chartDataCache.containsKey(cacheKey) || _isLoadingChart[cacheKey] == true) {
      return;
    }
    setState(() => _isLoadingChart[cacheKey] = true);
    try {
      final userProvider = UserProvider.instance;
      final token = userProvider.token;
      if (token == null || token.isEmpty) {
        setState(() => _isLoadingChart[cacheKey] = false);
        return;
      }
      final logs = await UserService.getChartLog(token, [realId]);
      logs.sort((a, b) => a.time.compareTo(b.time));
      final chartList = logs.map((log) => {
        'achievement': log.segaChartNew?.achievement ?? 0,
        'time': log.time,
        'scoreRank': log.segaChartNew?.scoreRank ?? 0,
        'comboStatus': log.segaChartNew?.comboStatus ?? 0,
        'syncStatus': log.segaChartNew?.syncStatus ?? 0,
        'deluxscoreMax': log.segaChartNew?.deluxscoreMax ?? 0,
        'playCount': log.segaChartNew?.playCount ?? 0,
      }).toList();
      setState(() {
        _chartDataCache[cacheKey] = chartList;
        _isLoadingChart[cacheKey] = false;
      });
    } catch (e) {
      print("Load UT chart error: $e");
      setState(() => _isLoadingChart[cacheKey] = false);
    }
  }

  Widget _buildAliasSection(List<String> rawAliases) {
    final uniqueAliases = rawAliases
        .where((e) => e != null && e.trim().isNotEmpty)
        .map((e) => e.trim())
        .toSet()
        .toList();

    if (uniqueAliases.isEmpty) return const SizedBox.shrink();

    final displayLimit = _isAliasExpanded ? uniqueAliases.length : 3;
    final displayedAliases = uniqueAliases.take(displayLimit).toList();
    final hasMore = uniqueAliases.length > 3;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Wrap(
          spacing: 6.0,
          runSpacing: 4.0,
          children: [
            ...displayedAliases.map((alias) => Container(
              decoration: BoxDecoration(
                color: Colors.grey.shade100,
                borderRadius: BorderRadius.circular(4),
                border: Border.all(color: Colors.grey.shade300, width: 0.5),
              ),
              padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
              child: Text(
                alias,
                style: TextStyle(
                  fontSize: 11,
                  color: Colors.grey[700],
                  fontStyle: FontStyle.italic,
                ),
              ),
            )).toList(),
          ],
        ),
        if (hasMore)
          InkWell(
            onTap: () {
              setState(() {
                _isAliasExpanded = !_isAliasExpanded;
              });
            },
            child: Padding(
              padding: const EdgeInsets.only(top: 4),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    _isAliasExpanded ? "收起" : "查看更多 (${uniqueAliases.length - 3})",
                    style: TextStyle(fontSize: 11),
                  ),
                  Icon(
                    _isAliasExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
                    size: 14,
                    color: Theme.of(context).primaryColor,
                  ),
                ],
              ),
            ),
          ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    // 【新增】如果存在预览 URL，则显示 WebView 页面
    if (_previewUrl != null) {
      return Scaffold(
        appBar: AppBar(
          title: const Text("谱面预览"),
          actions: [
            IconButton(
              icon: const Icon(Icons.close),
              onPressed: () {
                setState(() {
                  _previewUrl = null;
                });
              },
            ),
          ],
        ),
        body: WebViewWidget(controller: _webViewController),
      );
    }

    // 否则显示原有的详情页面
    final coverUrl = _getCoverUrl(widget.song.id);
    final diffs = _getCurrentDifficulties();
    final availableTypes = _getAvailableTypes();

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.song.title ?? "歌曲详情"),
        elevation: 2,
        actions: [
          if (_selectedType != 'UT' && _selectedType != null)
            IconButton(
              icon: _isDownloading
                  ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
                  : const Icon(Icons.download_rounded),
              tooltip: "下载 ${_selectedType} 谱面",
              onPressed: _isDownloading ? null : _downloadCurrentTypeAdx,
            ),
        ],
      ),
      // 【修改】使用 Column 布局，将固定内容和滚动内容分离
      body: Column(
        children: [
          // 1. 固定顶部：歌曲信息卡片
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
            child: Card(
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
              elevation: 4,
              shadowColor: Colors.purpleAccent.withOpacity(0.2),
              child: Padding(
                padding: const EdgeInsets.all(14),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10),
                      child: CacheImage.network(
                        coverUrl,
                        width: 90,
                        height: 90,
                        fit: BoxFit.cover,
                        errorBuilder: (_, __, ___) => Container(
                          width: 90,
                          height: 90,
                          color: Colors.grey[200],
                          child: const Icon(Icons.music_note, size: 36),
                        ),
                      ),
                    ),
                    const SizedBox(width: 14),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            "[${widget.song.id}] ${widget.song.title}",
                            style: const TextStyle(
                              fontSize: 17,
                              fontWeight: FontWeight.bold,
                            ),
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                          const SizedBox(height: 6),
                          Text(
                            "艺术家：${widget.song.artist ?? '未知'}",
                            style: const TextStyle(fontSize: 13),
                          ),
                          const SizedBox(height: 4),
                          if (widget.song.albums?.isNotEmpty == true)
                            _buildAliasSection(widget.song.albums!),
                          const SizedBox(height: 6),
                          Text(
                            "${widget.song.genre ?? ''}  |  ${widget.song.from ?? ''}",
                            style: TextStyle(fontSize: 12, color: Colors.grey[600]),
                          ),
                          const SizedBox(height: 2),
                          Text(
                            "BPM：${widget.song.bpm ?? '未知'}",
                            style: TextStyle(fontSize: 12, color: Colors.grey[600]),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),

          // 2. 滚动区域：难度详情
          Expanded(
            child: SingleChildScrollView(
              padding: const EdgeInsets.symmetric(horizontal: 12), // 注意：vertical padding 可以减小或移除，因为顶部已有 padding
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  if (availableTypes.isNotEmpty) ...[
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 4),
                      child: Row(
                        children: [
                          const Text(
                            "难度详情",
                            style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                          ),
                          const SizedBox(width: 12),
                          if (availableTypes.length > 1)
                            Expanded(
                              child: CupertinoSlidingSegmentedControl<String>(
                                groupValue: _selectedType,
                                backgroundColor: Colors.grey.shade200,
                                thumbColor: Theme.of(context).primaryColor,
                                children: {
                                  for (var type in availableTypes)
                                    type: Padding(
                                      padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
                                      child: Text(
                                        type,
                                        style: TextStyle(
                                          color: _selectedType == type ? Colors.white : Colors.black87,
                                          fontWeight: FontWeight.w600,
                                        ),
                                      ),
                                    ),
                                },
                                onValueChanged: (val) {
                                  if (val != null) setState(() => _selectedType = val);
                                },
                              ),
                            ),
                        ],
                      ),
                    ),
                    const SizedBox(height: 12),
                  ],

                  if (diffs.isEmpty)
                    const Center(
                      child: Padding(
                        padding: EdgeInsets.all(30),
                        child: Text("暂无谱面数据", style: TextStyle(color: Colors.grey)),
                      ),
                    )
                  else
                    ...diffs.map((item) => _diffItem(
                      type: item['type'],
                      diff: item['diff'],
                    )),

                  const SizedBox(height: 30),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  // 【修改】_diffItem 方法，增加预览按钮
  Widget _diffItem({required String type, required Map diff}) {
    int levelId = diff['level_id'] ?? 0;
    final double lvValue = double.tryParse(diff['level_value']?.toString() ?? '') ?? 0;
    final designer = diff['note_designer'] ?? "-";
    final notes = diff['notes'] ?? <String, dynamic>{};
    final total = notes['total'] ?? 0;
    final tap = notes['tap'] ?? 0;
    final hold = notes['hold'] ?? 0;
    final slide = notes['slide'] ?? 0;
    final brk = notes['break_'] ?? 0;

    int realId;
    String? utTitleName;
    String cacheKey = "";

    if (type == 'UT') {
      realId = (diff['id'] as num?)?.toInt() ?? 0;
      final utTitleMap = widget.song.utTitle as Map?;
      if (utTitleMap != null) {
        final key = diff['id'].toString();
        utTitleName = utTitleMap[key]?.toString();
      }
      cacheKey = "UT_$realId";
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _loadUtChartData(cacheKey, realId);
      });
    } else {
      realId = _getRealMusicId(type);
      cacheKey = type;
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _loadTypeChartData(type);
      });
    }

    List<Map<String, dynamic>> chartHistory = [];
    if (_chartDataCache.containsKey(cacheKey)) {
      if (type == 'UT') {
        chartHistory = _chartDataCache[cacheKey]!;
      } else {
        chartHistory = _chartDataCache[cacheKey]!
            .where((e) => e['level'] == levelId)
            .toList();
      }
    }
    bool hasScoreData = chartHistory.isNotEmpty;
    final score = widget.userScoreCache[realId]?[levelId];
    bool hasUserScore = score != null;

    String name = "";
    Color color = Colors.grey;
    bool isBanquet = type == 'UT';

    if (isBanquet) {
      color = Colors.pinkAccent;
      name = utTitleName ?? "UT 宴会谱";
    } else {
      switch (levelId) {
        case 0: name = "$type Basic"; color = Colors.green; break;
        case 1: name = "$type Advanced"; color = Colors.yellow.shade700; break;
        case 2: name = "$type Expert"; color = Colors.red; break;
        case 3: name = "$type Master"; color = Colors.purple; break;
        case 4: name = "$type Re:Master"; color = Colors.purpleAccent.shade100; break;
        default: name = type;
      }
    }

    final rating990 = _calculateRating(lvValue, 99.0);
    final rating995 = _calculateRating(lvValue, 99.5);
    final rating1000 = _calculateRating(lvValue, 100.0);
    final rating1003 = _calculateRating(lvValue, 100.3);
    final rating1005 = _calculateRating(lvValue, 100.5);

    return Card(
      margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
      elevation: 5,
      shadowColor: color.withOpacity(0.2),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
                  decoration: BoxDecoration(
                    color: color.withOpacity(0.15),
                    borderRadius: BorderRadius.circular(8),
                    border: Border.all(color: color.withOpacity(0.4), width: 1.2),
                  ),
                  child: Text(
                    isBanquet ? name : "$name (${lvValue.toStringAsFixed(1)})",
                    style: TextStyle(
                      color: color,
                      fontWeight: FontWeight.bold,
                      fontSize: 15,
                    ),
                  ),
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    if (hasUserScore)
                      const Icon(Icons.star_rounded, color: Colors.amber, size: 22),
                    const SizedBox(width: 8),
                    // 【新增】谱面预览按钮
                    IconButton(
                      icon: const Icon(Icons.preview_rounded, size: 22),
                      tooltip: "查看谱面预览",
                      onPressed: () {
                        // 构造 URL
                        // 规则: https://maimai.lxns.net/chart?chart_id={id}&difficulty={level}
                        int chartId;
                        if (type == 'SD') {
                          chartId = widget.song.id;
                        } else if (type == 'DX') {
                          chartId = widget.song.id + 10000;
                        } else {
                          // UT 情况，通常 UT 的 ID 在 diff['id'] 中，或者需要特殊处理
                          // 这里假设 UT 也使用类似的 ID 逻辑，如果 lxns 支持 UT 预览的话
                          // 如果 lxns 不支持 UT，可以禁用此按钮或提示
                          chartId = (diff['id'] as num?)?.toInt() ?? 0;
                        }

                        final url = "https://maimai.lxns.net/chart?chart_id=$chartId&difficulty=$levelId";

                        // 加载 URL 并切换视图
                        _webViewController.loadRequest(Uri.parse(url));
                        setState(() {
                          _previewUrl = url;
                        });
                      },
                    ),
                  ],
                ),
              ],
            ),
            const SizedBox(height: 10),
            Text("谱师：$designer", style: const TextStyle(fontSize: 14)),
            const SizedBox(height: 8),

            Table(
              columnWidths: const {
                0: FixedColumnWidth(40),
                1: FixedColumnWidth(40),
                2: FixedColumnWidth(40),
                3: FixedColumnWidth(40),
                4: FixedColumnWidth(40),
              },
              children: [
                TableRow(
                  children: [
                    _tableCell("总物量", color),
                    _tableCell("TAP", color),
                    _tableCell("HOLD", color),
                    _tableCell("SLIDE", color),
                    _tableCell("BRK", color),
                  ],
                ),
                TableRow(
                  children: [
                    _tableCell(total.toString(), color, isHeader: false),
                    _tableCell(tap.toString(), color, isHeader: false),
                    _tableCell(hold.toString(), color, isHeader: false),
                    _tableCell(slide.toString(), color, isHeader: false),
                    _tableCell(brk.toString(), color, isHeader: false),
                  ],
                ),
              ],
            ),
            const SizedBox(height: 10),

            Table(
              columnWidths: const {
                0: FixedColumnWidth(50),
                1: FixedColumnWidth(50),
                2: FixedColumnWidth(50),
                3: FixedColumnWidth(50),
                4: FixedColumnWidth(50),
                5: FixedColumnWidth(50),
              },
              children: [
                TableRow(
                  children: [
                    _tableCell("完成度", color),
                    _tableCell("99.0%", color),
                    _tableCell("99.5%", color),
                    _tableCell("100.0%", color),
                    _tableCell("100.3%", color),
                    _tableCell("100.5%", color),
                    _tableCell("", color),
                  ],
                ),
                TableRow(
                  children: [
                    _tableCell("Rating", color, isHeader: false),
                    _tableCell(rating990.toStringAsFixed(2), color, isHeader: false),
                    _tableCell(rating995.toStringAsFixed(2), color, isHeader: false),
                    _tableCell(rating1000.toStringAsFixed(2), color, isHeader: false),
                    _tableCell(rating1003.toStringAsFixed(2), color, isHeader: false),
                    _tableCell(rating1005.toStringAsFixed(2), color, isHeader: false),
                    _tableCell("", color, isHeader: false),
                  ],
                ),
              ],
            ),

            const SizedBox(height: 14),

            if (hasScoreData)
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text("推分进程", style: TextStyle(fontSize: 13, color: Colors.grey)),
                      Text(
                        "最近: ${(chartHistory.last['achievement'] / 10000.0).toStringAsFixed(4)}%",
                        style: TextStyle(fontSize: 13, color: color, fontWeight: FontWeight.w600),
                      ),
                    ],
                  ),
                  const SizedBox(height: 8),
                  ScoreProgressChart(
                    historyScores: chartHistory,
                    lineColor: color,
                    fillColor: color,
                  ),
                ],
              )
            else
              const Padding(
                padding: EdgeInsets.symmetric(vertical: 8),
                child: Text("暂无历史记录", style: TextStyle(fontSize: 13, color: Colors.grey)),
              ),

            if (hasUserScore) ...[
              const SizedBox(height: 12),
              Divider(height: 1, color: Colors.grey[300]),
              const SizedBox(height: 12),
              _buildScoreInfo(score!,diff),
            ],
          ],
        ),
      ),
    );
  }

  Widget _tableCell(String text, Color color, {bool isHeader = true}) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 4),
        child: Text(
          text,
          style: TextStyle(
            fontSize: isHeader ? 11 : 12,
            color: isHeader ? color : color.withOpacity(0.99),
            fontWeight: isHeader ? FontWeight.bold : FontWeight.w500,
          ),
        ),
      ),
    );
  }

  static int _calculateRating(double diff, double achievementPercent) {
    double sys = 22.4;
    double ach = achievementPercent;

    if (ach >= 100.5000) {
      return (diff * 22.512).floor();
    }
    if (ach == 100.4999) {
      sys = 22.2;
    } else if (ach >= 100.0000) {
      sys = 21.6;
    } else if (ach == 99.9999) {
      sys = 21.4;
    } else if (ach >= 99.5000) {
      sys = 21.1;
    } else if (ach >= 99.0000) {
      sys = 20.8;
    } else if (ach >= 98.0000) {
      sys = 20.3;
    } else if (ach >= 97.0000) {
      sys = 20.0;
    } else if (ach >= 94.0000) {
      sys = 16.8;
    } else if (ach >= 90.0000) {
      sys = 15.2;
    } else if (ach >= 80.0000) {
      sys = 13.6;
    } else if (ach >= 75.0000) {
      sys = 12.0;
    } else if (ach >= 70.0000) {
      sys = 11.2;
    } else if (ach >= 60.0000) {
      sys = 9.6;
    } else if (ach >= 50.0000) {
      sys = 8.0;
    } else {
      sys = 0.0;
    }

    if (sys == 0.0) return 0;
    return (diff * sys * ach / 100).floor();
  }

  Widget _buildScoreInfo(Map<String, dynamic> score, Map diff) {
    final ach = (score['achievement'] ?? 0) / 10000;
    final rank = _getRankText(score['scoreRank'] ?? 0);
    final dxScore = score['deluxscoreMax'] ?? 0;
    final playCount = score['playCount'] ?? 0;
    final rating = score['rating'] ?? 0;

    int comboStatus = score['comboStatus'] ?? 0;
    int syncStatus = score['syncStatus'] ?? 0;

    Color achColor = _getColorByAchievement(ach);
    Color rankColor = _getColorByRank(rank);

    int totalNotes = diff['notes']['total'] ?? 0;
    int allDx = totalNotes * 3;
    double perc = allDx > 0 ? dxScore / allDx : 0.0;

    String? comboIconPath;
    switch (comboStatus) {
      case 1: comboIconPath = "images/UI_MSS_MBase_Icon_FC.png"; break;
      case 2: comboIconPath = "images/UI_MSS_MBase_Icon_FCp.png"; break;
      case 3: comboIconPath = "images/UI_MSS_MBase_Icon_AP.png"; break;
      case 4: comboIconPath = "images/UI_MSS_MBase_Icon_APp.png"; break;
    }

    String? syncIconPath;
    switch (syncStatus) {
      case 1: syncIconPath = "images/UI_MSS_MBase_Icon_FS.png"; break;
      case 2: syncIconPath = "images/UI_MSS_MBase_Icon_FSp.png"; break;
      case 3: syncIconPath = "images/UI_MSS_MBase_Icon_FSD.png"; break;
      case 4: syncIconPath = "images/UI_MSS_MBase_Icon_FSDp.png"; break;
      case 5: syncIconPath = "images/UI_MSS_MBase_Icon_Sync.png"; break;
    }

    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Row(
                children: [
                  Icon(Icons.emoji_events_rounded, color: Colors.amber, size: 18),
                  SizedBox(width: 4),
                  Text(
                    "你的成绩",
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 15,
                      height: 1.1,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 10),
              Row(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  GradientText(
                    data:"${ach.toStringAsFixed(4)}%",
                    style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
                    gradientLayers: [
                      GradientLayer(
                        gradient: const LinearGradient(
                          colors: [Colors.pinkAccent, Colors.blue],
                        ),
                        blendMode: BlendMode.srcIn,
                      ),
                    ],
                  ),
                  const SizedBox(width: 8),
                  _buildTag(rank, rankColor),
                  if (comboIconPath != null)
                    Padding(
                      padding: const EdgeInsets.only(left: 2),
                      child: Image.asset(comboIconPath, width: 40, height: 40),
                    ),
                  if (syncIconPath != null)
                    Padding(
                      padding: const EdgeInsets.only(left: 4),
                      child: Image.asset(syncIconPath, width: 40, height: 40),
                    ),
                ],
              ),
              const SizedBox(height: 12),
              Row(
                children: [
                  const Icon(Icons.score_rounded, size: 14, color: Colors.blueGrey),
                  const SizedBox(width: 4),
                  Text("DX：$dxScore / $allDx", style: TextStyle(fontSize: 13, color: Colors.grey[700])),
                  const SizedBox(width: 10),
                  if (perc >= 0.85)
                    Padding(
                      padding: const EdgeInsets.only(right: 4),
                      child: _getDxStarIcon(perc),
                    ),
                  const Spacer(),
                  Icon(Icons.star_rate_rounded, size: 14, color: Colors.amber),
                  const SizedBox(width: 3),
                  Text("Rating：$rating", style: TextStyle(fontSize: 12, color: Colors.grey[700], fontWeight: FontWeight.w500)),
                  const SizedBox(width: 10),
                  Icon(Icons.play_circle_outline_rounded, size: 14, color: Colors.grey[600]),
                  const SizedBox(width: 3),
                  Text("$playCount 次", style: TextStyle(fontSize: 12, color: Colors.grey[600])),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _getDxStarIcon(double perc) {
    String assetPath;
    if (perc >= 0.97) {
      assetPath = "images/UI_GAM_Gauge_DXScoreIcon_05.png";
    } else if (perc >= 0.95) {
      assetPath = "images/UI_GAM_Gauge_DXScoreIcon_04.png";
    } else if (perc >= 0.93) {
      assetPath = "images/UI_GAM_Gauge_DXScoreIcon_03.png";
    } else if (perc >= 0.90) {
      assetPath = "images/UI_GAM_Gauge_DXScoreIcon_02.png";
    } else if (perc >= 0.85) {
      assetPath = "images/UI_GAM_Gauge_DXScoreIcon_01.png";
    } else {
      return const SizedBox();
    }
    return Image.asset(assetPath, width: 30, height: 30, fit: BoxFit.contain);
  }

  Widget _buildTag(String text, Color color) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
      decoration: BoxDecoration(
        color: color.withOpacity(0.15),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: color.withOpacity(0.5), width: 1.2),
      ),
      child: Text(
        text,
        style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 14),
      ),
    );
  }

  Color _getColorByAchievement(double ach) {
    if (ach >= 100.5) return const Color(0xFFD4AF37);
    if (ach >= 100.0) return Colors.purple;
    if (ach >= 99.5) return Colors.purpleAccent;
    if (ach >= 99.0) return Colors.deepPurple;
    if (ach >= 98.0) return Colors.lightBlue;
    if (ach >= 97.0) return Colors.blue;
    return Colors.green;
  }

  Color _getColorByRank(String rank) {
    if (rank.contains("SSS+")) return const Color(0xFFD4AF37);
    if (rank.contains("SSS")) return Colors.purple;
    if (rank.contains("SS+") || rank.contains("SS")) return Colors.deepPurple;
    if (rank.contains("S+") || rank.contains("S")) return Colors.blue;
    return Colors.green;
  }

  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";
    }
  }

  String _getRankText(int rank) {
    switch (rank) {
      case 13: return "SSS+";
      case 12: return "SSS";
      case 11: return "SS+";
      case 10: return "SS";
      case 9: return "S+";
      case 8: return "S";
      case 7: return "AAA";
      case 6: return "AA";
      case 5: return "A";
      case 4: return "BBB";
      case 3: return "BB";
      case 2: return "B";
      case 1: return "C";
      default: return "D";
    }
  }

  int _getRealMusicId(String type) {
    if (type == "SD") return widget.song.id;
    if (type == "DX") return 10000 + widget.song.id;
    return 100000 + widget.song.id;
  }
}