import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:unionapp/service/steganography_util.dart';
import '../model/song_model.dart';
import '../model/user_model.dart';
import '../tool/encryption_util.dart';
import 'dart:typed_data';

class UserService {
  static final Dio _dio = Dio();
  static const String baseUrl = "https://union.godserver.cn";

  // 注册
  static Future<void> register(String username, String password, String inviter) async {
    try {
      await _dio.post(
        '$baseUrl/user/register',
        data: {
          "username": username,
          "password": password,
          "inviter": inviter,
        },
      );
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  // 登录
  static Future<String> login(String username, String twoKeyCode) async {
    try {
      final raw = jsonEncode({
        "username": username,
        "twoKeyCode": twoKeyCode,
      });
      final encrypted = EncryptionUtil.encrypt(raw);

      final res = await _dio.post(
        '$baseUrl/api/user/user',
        data: {
          "code": 200,
          "timestamp": DateTime.now().millisecondsSinceEpoch,
          "msg": "login",
          "data": encrypted,
        },
      );

      return EncryptionUtil.decrypt(res.data["data"]?.toString() ?? '');
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  // 获取用户信息
  static Future<UserModel> getUserInfo(String token) async {
    try {
      final res = await _dio.post(
        '$baseUrl/api/user/data',
        data: {
          "msg": "getUser",
          "timestamp": DateTime.now().millisecondsSinceEpoch,
          "data": token,
        },
        options: Options(headers: {"Authorization": token}),
      );

      final decrypted = EncryptionUtil.decrypt(res.data["data"]?.toString() ?? '');
      return UserModel.fromJson(jsonDecode(decrypted));
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  // 保存/修改用户信息（updateUser）
  static Future<String> updateUser(String token, String encryptedData) async {
    try {
      final res = await _dio.put(
        '$baseUrl/api/user/data',
        data: {
          "msg": "updateUser",
          "timestamp": DateTime.now().millisecondsSinceEpoch,
          "data": encryptedData,
        },
        options: Options(headers: {"Authorization": token}),
      );
      return res.data.toString();
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
    return "";
  }

  // 检查登录状态
  static Future<bool> isLogin(String token) async {
    try {
      final res = await _dio.get(
        '$baseUrl/api/user/isLogin',
        options: Options(headers: {"Authorization": token}),
      );
      return res.data["code"] == 200;
    } on DioException {
      return false;
    }
  }

  // 刷新Token（接口通用逻辑）
  static Future<String?> refreshToken(String oldToken) async {
    try {
      final res = await _dio.post(
        '$baseUrl/api/user/refreshToken',
        options: Options(headers: {"Authorization": oldToken}),
      );
      if (res.data["code"] == 200) {
        return res.data["data"]?.toString();
      }
      return null;
    } on DioException {
      return null;
    }
  }

  // 获取角色
  static Future<String?> getUserRole(String token) async {
    try {
      final res = await _dio.get(
        '$baseUrl/api/user/role',
        options: Options(headers: {"Authorization": token}),
      );
      if (res.data["code"] == 200) {
        return res.data["data"]?.toString();
      }
      return null;
    } on DioException {
      return null;
    }
  }

  // 获取性别标签
  static Future<List<String>> fetchSexTags() async {
    try {
      final res = await _dio.get('$baseUrl/api/union/sextag');
      if (res.data is List) {
        return List<String>.from(res.data);
      }
      return [];
    } on DioException {
      return [];
    }
  }

  // 获取好友列表
  static Future<List<dynamic>> fetchFriends(String token) async {
    try {
      final res = await _dio.get(
        '$baseUrl/api/user/friend',
        options: Options(headers: {"Authorization": token}),
      );
      if (res.data is List) {
        return res.data;
      }
      return [];
    } on DioException {
      return [];
    }
  }

  // 更新API Key
  static Future<void> updateApiKey(String token) async {
    try {
      await _dio.post(
        '$baseUrl/api/user/updateKey',
        data: {
          "msg": "updateApiKey",
          "timestamp": DateTime.now().millisecondsSinceEpoch,
        },
        options: Options(headers: {"Authorization": token}),
      );
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  // 绑定GitHub - 获取跳转链接
  static Future<String> bindGithub(String token) async {
    try {
      final res = await _dio.get(
        '$baseUrl/api/user/bind/github',
        options: Options(headers: {"Authorization": token}),
      );
      return res.realUri.toString();
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  // 确认绑定GitHub
  static Future<void> confirmBindGithub(String token, String uuid) async {
    try {
      await _dio.post(
        '$baseUrl/api/user/bind/github',
        options: Options(headers: {
          "Authorization": token,
          "uuid": uuid,
        }),
      );
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  // 验证SegaId
  static Future<Map<String, dynamic>> verifySegaId(String token, String segaId) async {
    try {
      final res = await _dio.post(
        '$baseUrl/api/user/verifySegaId',
        queryParameters: {"useSegaId": segaId},
        options: Options(headers: {"Authorization": token}),
      );
      return res.data;
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }
// 获取雷达图数据
  static Future<Map<String, dynamic>> getRadarData(String token, String id) async {
    try {
      final res = await _dio.get(
        '$baseUrl/api/union/radar',
        queryParameters: {"id": id},
        options: Options(headers: {"Authorization": token}),
      );
      // 返回雷达图原始数据
      return Map<String, dynamic>.from(res.data);
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }
  // 统一错误处理
  static String _getErrorMessage(DioException e) {
    if (e.response?.data != null) {
      final data = e.response!.data;
      if (data is Map && data["msg"] != null) {
        return data["msg"].toString();
      }
    }
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.receiveTimeout:
      case DioExceptionType.sendTimeout:
        return "网络超时";
      case DioExceptionType.connectionError:
        return "网络异常";
      default:
        return "请求失败";
    }
  }
  static Future<Map<String, dynamic>> getUserAllScores(String token, {String? name}) async {
    try {
      // 构建查询参数
      final queryParameters = <String, dynamic>{};
      if (name != null && name.isNotEmpty) {
        queryParameters['name'] = name;
      }
      final res = await _dio.get(
        '$baseUrl/api/union/reisaRating',
        queryParameters: queryParameters,
        options: Options(headers: {"Authorization": token}),
      );
      if (res.data is Map) {
        return Map<String, dynamic>.from(res.data);
      }
      return {};
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }
  static Future<Map<String, dynamic>> getSegaRatingData(String token, String segaId) async {
    try {
      final res = await _dio.get(
        '$baseUrl/api/union/segaReisaRating',
        queryParameters: {"segaId": segaId},
        options: Options(headers: {"Authorization": token}),
      );
      return Map<String, dynamic>.from(res.data);
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }
  // 上传 Sega 成绩数据
  static Future<Map<String, dynamic>> uploadSegaRating(
      String token,
      String segaId,
      Map<String, dynamic> segaResult,
      ) async {
    try {
      final res = await _dio.post(
        '$baseUrl/api/union/segaReisaRating',
        queryParameters: {
          "segaId": segaId,
        },
        data: segaResult,
        options: Options(
          headers: {
            "Authorization": token,
          },
        ),
      );
      return Map<String, dynamic>.from(res.data);
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }

  static Future<List<ChartLogModel>> getChartLog(String token, List<int> musicIds) async {
    try {
      print("getChartLog");
      // 构建查询参数
      // 如果 API 期望的是逗号分隔的字符串 "11434,11435"
      final String idsParam = musicIds.map((e) => e.toString()).join(',');

      final res = await _dio.get(
        '$baseUrl/api/union/chartlog',
        queryParameters: {
          "musicId": idsParam,
        },
        options: Options(headers: {"Authorization": token}),
      );

      // 检查返回数据是否为 List
      if (res.data is List) {
        return (res.data as List)
            .map((item) => ChartLogModel.fromJson(item as Map<String, dynamic>))
            .toList();
      }

      // 如果后端在某些错误情况下返回 Map 而不是 List，这里返回空列表或抛出异常
      return [];
    } on DioException catch (e) {
      throw _getErrorMessage(e);
    }
  }
  /// 上传隐写图片
  /// [token] 用户令牌
  /// [segaId] 要隐藏的 Sega ID
  /// [originalImageBytes] 原始图片字节数据 (Uint8List)
  static Future<Map<String, dynamic>> uploadStegImage({
    required String token,
    required String segaId,
    required Uint8List originalImageBytes,
  }) async {
    try {
      // 1. 拼接隐写数据（SGWCMAID 开头）
      final secretData = '$segaId';
      print(secretData);

      // 2. 执行隐写 + 加密
      // 使用 Uint8List.fromList 确保类型兼容，避免 typed_data_patch 错误
      final safeImageBytes = Uint8List.fromList(originalImageBytes);

      final stegImageBytes = SteganographyUtil.hideDataInImage(
        safeImageBytes,
        secretData,
      );

      // 3. 构建上传表单
      final formData = FormData.fromMap({
        'path': MultipartFile.fromBytes(
          stegImageBytes,
          filename: 'encoded.png',
          contentType: DioMediaType.parse('image/png'),
        ),
      });

      // 4. 前置接口（完全对齐 JS 逻辑）
      await _dio.get(
        '$baseUrl/api/sega/3egrsz53et/w35eshdk76e',
        options: Options(headers: {"Authorization": token}),
      );

      // 5. 【核心上传】隐写图片
      final res = await _dio.post(
        '$baseUrl/api/sega/phone',
        data: formData,
        options: Options(
          headers: {
            "Authorization": token,},
        ),
      );

      // 6. 后续接口链（对齐 JS 逻辑）
      await _dio.post(
        '$baseUrl/api/sega/454szhghs/45ustzdxzsd',
        options: Options(headers: {"Authorization": token}),
      );

      await _dio.get(
        '$baseUrl/api/sega/stxfghb347/b46se',
        options: Options(headers: {"Authorization": token}),
      );

      await _dio.put(
        '$baseUrl/api/sega/sertjdffgh/4666drzzf',
        options: Options(headers: {"Authorization": token}),
      );

      print(res.data);
      // 返回最终结果
      if (res.data is Map) {
        return Map<String, dynamic>.from(res.data);
      }
      return {"code": 200, "msg": "success", "data": res.data};

    } on DioException catch (e) {
      throw _getErrorMessage(e);
    } catch (e) {
      throw Exception("隐写或上传失败: $e");
    }
  }
}