// update_service.dart
import 'dart:async';
import 'dart:io';

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

/// 安装 MethodChannel 名称（与原生保持一致）
const String _kInstallChannel = 'app.install';

/// 更新事件类型
enum UpdateState { idle, starting, downloading, completed, installing, installed, failed, canceled }

class UpdateEvent {
  final UpdateState state;
  final String? message; // 可选的错误/提示消息

  UpdateEvent(this.state, {this.message});
}

/// 单例服务类：管理下载、进度与安装
class UpdateService {
  UpdateService._internal();

  static final UpdateService _instance = UpdateService._internal();

  factory UpdateService() => _instance;

  // 进度通知器（0.0 ~ 1.0）
  final ValueNotifier<double> progress = ValueNotifier<double>(0.0);

  // 状态流控制器（广播）
  final StreamController<UpdateEvent> _statusController =
  StreamController<UpdateEvent>.broadcast();

  Stream<UpdateEvent> get statusStream => _statusController.stream;

  // Dio cancel token 用于取消下载
  CancelToken? _cancelToken;

  final MethodChannel _channel = const MethodChannel(_kInstallChannel);

  /// 启动下载并在下载完成后尝试安装
  /// apkUrl: 下载地址
  /// apkFileName: 保存的文件名（可选）
  Future<void> downloadAndInstall({
    required String apkUrl,
    String? apkFileName,
  }) async {
    // 防止重复下载
    if (_cancelToken != null && !_cancelToken!.isCancelled) {
      _statusController.add(UpdateEvent(UpdateState.failed, message: '已有下载进行中'));
      return;
    }

    _statusController.add(UpdateEvent(UpdateState.starting));
    progress.value = 0.0;

    _cancelToken = CancelToken();

    // 准备保存路径（app 专属外部目录）
    String savePath;
    try {
      final extDir = await getExternalStorageDirectory();
      if (extDir == null) {
        _statusController.add(UpdateEvent(UpdateState.failed, message: '无法获取存储目录'));
        return;
      }
      apkFileName ??= 'app_update_${DateTime.now().millisecondsSinceEpoch}.apk';
      savePath = '${extDir.path}/$apkFileName';
    } catch (e) {
      _statusController.add(UpdateEvent(UpdateState.failed, message: '获取存储路径失败: $e'));
      return;
    }

    final dio = Dio();

    try {
      _statusController.add(UpdateEvent(UpdateState.downloading));
      await dio.download(
        apkUrl,
        savePath,
        cancelToken: _cancelToken,
        onReceiveProgress: (received, total) {
          if (total > 0) {
            final p = received / total;
            progress.value = p;
          }
        },
        options: Options(
          responseType: ResponseType.stream,
          followRedirects: true,
          // 不设置超时（可能大文件下载）
          receiveTimeout: Duration(seconds: 0),
          headers: {"Accept": "application/vnd.android.package-archive"},
        ),
      );

      // 下载完成
      progress.value = 1.0;
      _statusController.add(UpdateEvent(UpdateState.completed));

      // 延迟让 UI 显示 100%
      await Future.delayed(const Duration(milliseconds: 200));

      // 调用原生安装
      _statusController.add(UpdateEvent(UpdateState.installing));
      try {
        final Map<String, dynamic> args = {'path': savePath};
        await _channel.invokeMethod('installApk', args);
        // 成功发起安装（系统会弹出安装界面），我们不能保证用户安装成功，但这里当做已触发安装
        _statusController.add(UpdateEvent(UpdateState.installed));
      } on PlatformException catch (e) {
        _statusController.add(UpdateEvent(UpdateState.failed, message: '安装失败: ${e.message}'));
      } catch (e) {
        _statusController.add(UpdateEvent(UpdateState.failed, message: '安装异常: $e'));
      }
    } on DioError catch (e) {
      if (CancelToken.isCancel(e)) {
        progress.value = 0.0;
        _statusController.add(UpdateEvent(UpdateState.canceled));
      } else {
        progress.value = 0.0;
        _statusController.add(UpdateEvent(UpdateState.failed, message: e.message));
      }
    } catch (e) {
      progress.value = 0.0;
      _statusController.add(UpdateEvent(UpdateState.failed, message: e.toString()));
    } finally {
      // 清理 token
      _cancelToken = null;
    }
  }

  /// 取消当前下载（若有）
  void cancelDownload() {
    if (_cancelToken != null && !_cancelToken!.isCancelled) {
      _cancelToken!.cancel();
    }
  }

  /// 仅触发安装（如果你已经手动下载好了文件），传入本地 apk 路径
  Future<void> installApk(String apkPath) async {
    try {
      _statusController.add(UpdateEvent(UpdateState.installing));
      final Map<String, dynamic> args = {'path': apkPath};
      await _channel.invokeMethod('installApk', args);
      _statusController.add(UpdateEvent(UpdateState.installed));
    } on PlatformException catch (e) {
      _statusController.add(UpdateEvent(UpdateState.failed, message: '安装失败: ${e.message}'));
    } catch (e) {
      _statusController.add(UpdateEvent(UpdateState.failed, message: '安装异常: $e'));
    }
  }

  /// 释放资源（页面销毁或 app 退出时调用）
  Future<void> dispose() async {
    try {
      _statusController.add(UpdateEvent(UpdateState.idle));
      await _statusController.close();
    } catch (_) {}
    try {
      progress.dispose();
    } catch (_) {}
  }
}
