import 'dart:io';
import 'dart:math';

import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_online_url.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:video_thumbnail/video_thumbnail.dart';

import 'package:yumi/shared/data_sources/sources/local/file_cache_manager.dart';
import 'package:yumi/shared/business_logic/models/res/sc_user_red_packet_send_res.dart';

class SCMessageUtils {
  //私聊红包Future缓存
  static Map<String, Future<SCUserRedPacketSendRes>> redPacketFutureCache = {};

  static Future<File> createImageElem(File file) async {
    try {
      // 2. 获取文件信息
      final originalSize = file.lengthSync();
      final fileExtension = _ge(file.path).toLowerCase();
      print('压缩前文件: ${file.path}');
      print('文件类型: $fileExtension');
      print('压缩前大小: ${_fs(originalSize)}');

      // 3. 小文件不压缩（小于 100KB）
      if (originalSize < 100 * 1024) {
        print('文件较小，跳过压缩');
        return file;
      }

      // 4. GIF 文件特殊处理
      if (fileExtension == 'gif') {
        print('GIF 文件，使用特殊处理');
        return await _gf(file);
      }

      // 5. 创建临时目录和文件
      final directory = await getTemporaryDirectory();
      final timestamp = DateTime.now().millisecondsSinceEpoch;
      final String fileName =
          'compressed_${timestamp}_${_fh(file)}.jpg';
      final File newFile = File("${directory.path}/$fileName");

      // 6. 动态调整压缩质量（根据原文件大小）
      final int quality = _cq(originalSize);
      print('使用压缩质量: $quality%');

      // 7. 执行压缩
      final XFile? compressedFile =
          await FlutterImageCompress.compressAndGetFile(
            file.absolute.path,
            newFile.path,
            quality: quality,
            minWidth: 480,
            // 设置最小宽度，保持图片可用性
            minHeight: 480,
            // 设置最小高度
            rotate: 0,
            format: CompressFormat.jpeg,
            inSampleSize: _ss(originalSize), // 采样率，减少内存使用
          );

      if (compressedFile == null) {
        print('压缩失败，返回原文件');
        return file;
      }

      // 8. 检查压缩效果
      final compressedSize = await compressedFile.length();
      final compressionRatio =
          (originalSize - compressedSize) / originalSize * 100;

      print('压缩后大小: ${_fs(compressedSize)}');
      print('压缩率: ${compressionRatio.toStringAsFixed(1)}%');

      // 9. 如果压缩后文件反而更大，返回原文件
      if (compressedSize >= originalSize) {
        print('压缩后文件更大，返回原文件');
        await newFile.delete(); // 删除无用的压缩文件
        return file;
      }

      // 10. 缓存管理
      File localFile = File(compressedFile.path);
      final String cacheKey = _fh(localFile);
      await FileCacheManager.getInstance().putFileFromFile(cacheKey, localFile);

      print('压缩成功，发送路径: ${compressedFile.path}');
      return localFile;
    } catch (e) {
      print('图片压缩异常: $e');
      return file; // 异常时返回原文件，保证功能可用
    }
  }

  // 获取文件扩展名
  static String _ge(String path) {
    return path.split('.').last;
  }

  // 格式化文件大小显示
  static String _fs(int bytes) {
    if (bytes <= 0) return "0 B";
    const suffixes = ["B", "KB", "MB", "GB"];
    final i = (log(bytes) / log(1024)).floor();
    return '${(bytes / pow(1024, i)).toStringAsFixed(1)} ${suffixes[i]}';
  }

  // 计算压缩质量（根据文件大小动态调整）
  static int _cq(int fileSize) {
    if (fileSize > 5 * 1024 * 1024) {
      // > 5MB
      return 50;
    } else if (fileSize > 2 * 1024 * 1024) {
      // 2-5MB
      return 60;
    } else if (fileSize > 1 * 1024 * 1024) {
      // 1-2MB
      return 70;
    } else if (fileSize > 500 * 1024) {
      // 500KB-1MB
      return 80;
    } else {
      return 85; // < 500KB 使用较高质量
    }
  }

  // 计算采样率
  static int _ss(int fileSize) {
    if (fileSize > 5 * 1024 * 1024) return 4;
    if (fileSize > 2 * 1024 * 1024) return 3;
    if (fileSize > 1 * 1024 * 1024) return 2;
    return 1;
  }

  // 生成文件哈希（用于缓存键）
  static String _fh(File file) {
    final stats = file.statSync();
    return '${file.path}_${stats.modified.millisecondsSinceEpoch}'.hashCode
        .toString();
  }

  // GIF 文件压缩处理
  static Future<File> _gf(File file) async {
    // 对于 GIF，我们可以考虑：
    // 1. 使用其他库处理（如 image 包）
    // 2. 调整尺寸但保持动图特性
    // 3. 或者直接返回原文件（保持动图效果）

    // 这里简单返回原文件，避免破坏 GIF 动画
    print('GIF 文件保持原样发送');
    return file;
  }

  static Future<String?> generateFileThumbnail(
    String videoPath,
    int maxHeight,
  ) async {
    try {
      final thumbnailPath = await VideoThumbnail.thumbnailFile(
        video: videoPath,
        thumbnailPath: (await getTemporaryDirectory()).path,
        // 保存到临时目录
        maxHeight: maxHeight,
        // 指定高度，宽度按比例缩放
        imageFormat: ImageFormat.PNG,
        quality: 75,
      );
      return thumbnailPath; // 返回文件路径，可用于 Image.file(File(thumbnailPath!))
    } catch (e) {
      print("生成缩略图文件时出错: $e");
      return null;
    }
  }

  ///下载多媒体消息
  static Future<V2TimCallback> downloadMessage({
    required String msgID,
    required int messageType,
    required int imageType, // 图片类型，仅messageType为图片消息是有效
    required bool isSnapshot, // 是否是视频封面，仅messageType为视频消息是有效
  }) async {
    var result = await TencentImSDKPlugin.v2TIMManager
        .getMessageManager()
        .downloadMessage(
          msgID: msgID,
          messageType: messageType,
          imageType: imageType,
          isSnapshot: isSnapshot,
        );
    return result;
  }

  Future<V2TimValueCallback<V2TimMessageOnlineUrl>> getMessageOnlineUrl({
    required String msgID,
  }) async {
    var result = await TencentImSDKPlugin.v2TIMManager
        .getMessageManager()
        .getMessageOnlineUrl(msgID: msgID);
    return result;
  }

  /// 清空与该联系人的所有单聊消息记录
  static Future<void> clearAllMessages(String userId) async {
    V2TimCallback clearResult = await TencentImSDKPlugin.v2TIMManager
        .getMessageManager()
        .clearC2CHistoryMessage(userID: userId); // 指定要清空消息的联系人ID[citation:2]
  }
}
