import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';

/// 下载状态
enum DownloadStatus {
  idle,
  downloading,
  verifying,
  completed,
  failed,
  cancelled,
}

/// 下载进度回调
typedef DownloadProgressCallback = void Function(int received, int total);

/// 下载管理器
/// 负责下载 APK 文件并验证完整性，支持断点续传
class DownloadManager {
  final Dio _dio = Dio();
  CancelToken? _cancelToken;
  DownloadStatus _status = DownloadStatus.idle;

  /// 当前下载状态
  DownloadStatus get status => _status;

  /// 下载 APK 文件（支持断点续传）
  Future<File?> downloadApk({
    required String url,
    required String sha256Expected,
    DownloadProgressCallback? onProgress,
  }) async {
    try {
      // 强制 HTTPS
      if (!url.startsWith('https://')) {
        debugPrint('Download URL must use HTTPS');
        _status = DownloadStatus.failed;
        return null;
      }

      _status = DownloadStatus.downloading;
      _cancelToken = CancelToken();

      final dir = await getExternalStorageDirectory() ??
          await getApplicationSupportDirectory();
      final savePath = '${dir.path}/app_update.apk';
      final tempPath = '${dir.path}/app_update.apk.tmp';
      final file = File(savePath);
      final tempFile = File(tempPath);

      // 检查是否有未完成的下载（断点续传）
      int downloadedBytes = 0;
      if (await tempFile.exists()) {
        downloadedBytes = await tempFile.length();
        debugPrint('Found partial download: $downloadedBytes bytes');
      }

      // 如果完整文件已存在则删除
      if (await file.exists()) {
        await file.delete();
      }

      debugPrint('Downloading APK to: $savePath (resume from: $downloadedBytes bytes)');

      // 使用流式下载以支持断点续传
      final response = await _dio.get<ResponseBody>(
        url,
        cancelToken: _cancelToken,
        options: Options(
          responseType: ResponseType.stream,
          receiveTimeout: const Duration(minutes: 10),
          sendTimeout: const Duration(minutes: 10),
          headers: downloadedBytes > 0
              ? {'Range': 'bytes=$downloadedBytes-'}
              : null,
        ),
      );

      // 获取总文件大小
      int totalBytes = 0;
      final contentLength = response.headers.value('content-length');
      final contentRange = response.headers.value('content-range');

      if (contentRange != null) {
        final match =
            RegExp(r'bytes \d+-\d+/(\d+)').firstMatch(contentRange);
        if (match != null) {
          totalBytes = int.parse(match.group(1)!);
        }
      } else if (contentLength != null) {
        totalBytes = int.parse(contentLength) + downloadedBytes;
      }

      debugPrint('Total file size: $totalBytes bytes');

      // 打开文件进行追加写入
      final sink = tempFile.openWrite(mode: FileMode.append);
      int receivedBytes = downloadedBytes;

      try {
        await for (final chunk in response.data!.stream) {
          sink.add(chunk);
          receivedBytes += chunk.length;

          if (totalBytes > 0) {
            onProgress?.call(receivedBytes, totalBytes);
          }
        }
        await sink.flush();
      } finally {
        await sink.close();
      }

      // 重命名临时文件为最终文件
      await tempFile.rename(savePath);

      debugPrint('Download completed');

      // 校验 SHA-256（仅在服务器提供了哈希值时校验）
      if (sha256Expected.isNotEmpty) {
        _status = DownloadStatus.verifying;
        final isValid = await _verifySha256(file, sha256Expected);
        if (!isValid) {
          debugPrint('SHA-256 verification failed');
          await file.delete();
          _status = DownloadStatus.failed;
          return null;
        }
        debugPrint('SHA-256 verified');
      } else {
        debugPrint('SHA-256 not provided, skipping verification');
      }

      _status = DownloadStatus.completed;
      return file;
    } on DioException catch (e) {
      if (e.type == DioExceptionType.cancel) {
        debugPrint('Download cancelled');
        _status = DownloadStatus.cancelled;
      } else {
        debugPrint('Download failed: $e');
        _status = DownloadStatus.failed;
      }
      return null;
    } catch (e) {
      debugPrint('Download failed: $e');
      _status = DownloadStatus.failed;
      return null;
    }
  }

  /// 取消下载
  void cancelDownload() {
    _cancelToken?.cancel('User cancelled download');
    _status = DownloadStatus.cancelled;
  }

  /// 重置状态
  void reset() {
    _cancelToken = null;
    _status = DownloadStatus.idle;
  }

  /// 校验文件 SHA-256
  Future<bool> _verifySha256(File file, String expectedSha256) async {
    try {
      final bytes = await file.readAsBytes();
      final digest = sha256.convert(bytes);
      final actualSha256 = digest.toString();

      debugPrint('Expected SHA-256: $expectedSha256');
      debugPrint('Actual SHA-256:   $actualSha256');

      return actualSha256.toLowerCase() == expectedSha256.toLowerCase();
    } catch (e) {
      debugPrint('SHA-256 verification error: $e');
      return false;
    }
  }

  /// 删除已下载的 APK 文件和临时文件
  Future<void> cleanupDownloadedApk() async {
    try {
      final dir = await getExternalStorageDirectory() ??
          await getApplicationSupportDirectory();
      final file = File('${dir.path}/app_update.apk');
      final tempFile = File('${dir.path}/app_update.apk.tmp');

      if (await file.exists()) {
        await file.delete();
        debugPrint('Cleaned up downloaded APK');
      }
      if (await tempFile.exists()) {
        await tempFile.delete();
        debugPrint('Cleaned up temporary APK file');
      }
    } catch (e) {
      debugPrint('Cleanup failed: $e');
    }
  }
}
