import 'dart:io';

import 'package:dio/dio.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:flutter/foundation.dart';
import 'package:install_plugin_custom/install_plugin_custom.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:platform_device_id/platform_device_id.dart';

import 'package:vitalapp/managers/interfaces/models/upgrade.dart';
import 'package:vitalapp/rpc.dart';
import 'package:vitalapp/store/store.dart';

import 'interfaces/upgrade.dart';

class UpgradeManager implements IUpgradeManager {
  static const _apkCacheRoot = "cache/install/";

  @override
  Future<String> getCurrentVersion() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    final version = packageInfo.version;
    return version;
  }

  @override
  Future<UpgradeCheckResultModel?> checkNewVersionArrival() async {
    try {
      final currVersion = await getCurrentVersion();
      logger.i("current version $currVersion.");
      final deviceId = await PlatformDeviceId.getDeviceId;
      final request = GetLastUpgradeRequest(
        clientVersion: currVersion,
        deviceSerialNumber: deviceId,
      );
      final result = await rpc.upgrade.getLastUpgradeAsync(request);
      final model = UpgradeCheckResultModel(
        version: result.version ?? '',
        isCoerce: result.isCoerce,
        notes: result.upgradeNotes ?? '',
        downloadUrl: result.upgradeFileUrl ?? '',
        isNeedUpdate: result.isNeedUpdate,
      );
      return model;
    } catch (e) {
      logger.e("UpgradeManager check new version arrival error.", e);
    }
    return null;
  }

  @override
  Future<bool> downloadPackage(
    String version,
    String url, {
    ValueChanged<double>? onProgress,
    CancelToken? cancelToken,
  }) async {
    try {
      final savePath = await _getApkFilePath(version);
      final dio = Dio();
      await dio.download(
        url,
        savePath,
        cancelToken: cancelToken,
        onReceiveProgress: (received, total) {
          if (total != -1) {
            // 计算进度
            final double progress = received / total;
            onProgress?.call(progress);
            logger.i(
                "UpgradeManager downloading install-apk: V$version, progress: ${(progress * 100).toStringAsFixed(0)}%.");
          }
        },
      );
      return true;
    } catch (e) {
      logger.e(
        "UpgradeManager download package error."
        "Version: $version , FileUrl: $url.",
        e,
      );
      return false;
    }
  }

  @override
  Future<void> install(String version) async {
    try {
      final packageInfo = await PackageInfo.fromPlatform();
      final appid = packageInfo.packageName;
      final apkPath = await _getApkFilePath(version);

      final result = await InstallPluginCustom.installApk(apkPath, appid);
      logger.i("Upgrade install apk v$version, result: $result.");
    } catch (e) {
      logger.e("Upgrade install apk v$version error.", e);
    }
  }

  static Future<String> _getApkFilePath(String version) async {
    final root = await getExternalStorageDirectory();
    return "${root!.path}/$_apkCacheRoot$version.apk";
  }

  @override
  Future<void> deleteFile(String version) async {
    try {
      final apkPath = await _getApkFilePath(version);
      final file = File(apkPath);
      file.deleteSync(); // 同步删除文件
    } catch (e) {
      logger.e("Upgrade deleteFile apk v$version error.", e);
    }
  }
}
