import 'dart:io';

import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:install_plugin/install_plugin.dart';
import 'package:package_info/package_info.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sk_base_mobile/apis/api.dart';
import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/config.dart';
import 'package:sk_base_mobile/models/app_config.dart';
import 'package:sk_base_mobile/services/service.dart';
import 'package:sk_base_mobile/util/device.util.dart';
import 'package:sk_base_mobile/util/logger_util.dart';
import 'package:sk_base_mobile/util/modal.util.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:sk_base_mobile/util/snack_bar.util.dart';
import 'package:sk_base_mobile/widgets/upgrade_confirm.dart';
import '../constants/constants.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';

class AppInfoService extends GetxService {
  static AppInfoService get to => Get.find();
  final versionNumber = RxString('');
  late AppConfig appConfig;
  final scale = RxDouble(1.0);
  final isLarge = RxBool(false);
  final isCameraing = RxBool(false);
  final downloadProgress = RxDouble(0.0);
  Future<AppInfoService> init() async {
    LoggerUtil()
        .info("[service-appInfo] Register app-related information service");

    try {
      await Future.wait([
        getDeviceInfo(),
        getPackageInfo() /* , getAppConfig(), getossPolicy() */
      ]);
      requestPermission();
    } catch (e) {
      LoggerUtil().error(e);
    }
    return this;
  }

  Future<void> setIsFirstInstall() async {
    await StorageService.to
        .setBool(CacheKeys.isFirstInstall, true, isWithUser: false);
  }

  bool checkIsFirstInstall() {
    bool? isFirstInstallCache =
        StorageService.to.getBool(CacheKeys.isFirstInstall, isWithUser: false);
    return isFirstInstallCache == null || !isFirstInstallCache;
  }

  Future<void> getDeviceInfo() async {
    // DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
    // if (Platform.isIOS) {
    //   iosDeviceInfo = await deviceInfo.iosInfo;
    //   if (iosDeviceInfo != null) {
    //     await StorageService.to.setString(
    //         CacheKeys.deviceUUID, iosDeviceInfo!.identifierForVendor!,
    //         isWithUser: false);
    //     await StorageService.to.setString(
    //         CacheKeys.deviceModel, iosDeviceInfo!.name,
    //         isWithUser: false);
    //   }
    // } else {
    //   androidDeviceInfo = await deviceInfo.androidInfo;
    //   await StorageService.to.setString(
    //       CacheKeys.deviceUUID, GloablConfig.DEVICE_UUID,
    //       isWithUser: false);
    //   await StorageService.to.setString(
    //       CacheKeys.deviceModel, GloablConfig.DEVICE_MODEL,
    //       isWithUser: false);
    // }
  }

  Future<void> getPackageInfo() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    versionNumber.value = packageInfo.version;
  }

  Future<void> getAppConfig() async {
    // if (StorageService.to.getString(CacheKeys.token, isWithUser: false) !=
    //     null) {
    //   final response = await Api.getAppConfig();
    //   if (response.data != null) {
    //     appConfig = AppConfig.fromJson(response.data['data']);
    //     await StorageService.to.setString(
    //         CacheKeys.appConfig, jsonEncode(appConfig.items!),
    //         isWithUser: false);
    //     if (appConfig.ver != null) {
    //       await StorageService.to
    //           .setString(CacheKeys.ver, appConfig.ver!, isWithUser: false);
    //     }
    //   }
    // }
  }

  // need token
  Future<void> getossPolicy() async {
    // if (StorageService.to.getString(CacheKeys.token, isWithUser: false) !=
    //     null) {
    //   final response = await Api.getOssPolicy();
    //   if (response.data != null) {
    //     ossPolicy = OssPolicy.fromJson(response.data['data']);
    //   }
    // }
  }
  Future<void> checkVersion({forceCheck = false}) async {
    final res = await Future.wait([
      Api.getSystemParamConfigByCode(SystemParamConfig.appVersion),
      Api.getSystemParamConfigByCode(SystemParamConfig.isForceUpgrade)
    ]);
    final newVersion = res[0].data;
    final isForceUpgrade = res[1].data;
    if (newVersion != null) {
      final currentVersion = await DeviceUtil.getAppVersion();
      if (newVersion != currentVersion) {
        ModalUtil.alert(
          // title: '有新版本',
          builder: (_) => UpgradeConfirm(
            onConfirm: () {
              upgradeApp(newVersion);
            },
            forceUpgrade: isForceUpgrade == '1',
          ),
          // contentText: isForceUpgrade == '1' ? '此版本非常重要，强制更新' : '请更新',
        );
      } else if (forceCheck) {
        SnackBarUtil().info('已经是最新版本');
      }
    }
  }

  Future<void> upgradeApp(String version) async {
    if (await checkPermission()) {
      /// 下载安卓更新包
      String url = '${GloablConfig.OSS_URL}/upload/shankuangtong_v$version.apk';

      /// 创建存储文件
      Directory? storageDir = await getExternalStorageDirectory();
      if (storageDir != null) {
        String storagePath = storageDir.path;
        File file = File('$storagePath/shankuangtong_v${version}.apk');

        if (!file.existsSync()) {
          file.createSync();
        }

        try {
          /// 下载
          downloadProgress.value = 0;
          Get.back();

          ModalUtil.alert(
              barrierDismissible: false,
              contentPadding: EdgeInsets.symmetric(vertical: 0),
              showActions: false,
              content:
                  // 进度条
                  Obx(
                () => Stack(
                  children: [
                    Container(
                      height: ScreenAdaper.height(40),
                      child: LinearProgressIndicator(
                        value: downloadProgress.value,
                      ),
                    ),
                    Positioned(
                        left: 0,
                        right: 0,
                        child: Text(
                          '${downloadProgress.value * 100}%',
                          textAlign: TextAlign.center,
                          style: TextStyle(fontSize: ScreenAdaper.height(30)),
                        ))
                  ],
                ),
              ));
          await DioService.dio.download(url, file.path,
              onReceiveProgress: (num received, num total) =>
                  onReceiveProgress(received, total),
              options: Options(
                responseType: ResponseType.bytes,
                followRedirects: false,
              ));
          Get.back();
          InstallPlugin.install(
            file.path,
          ).then((result) {}).catchError((error) {});
        } catch (e) {
          SnackBarUtil().warning('暂时无法更新，请重新下载安装, 或者请联系管理员');
        }
      }
    }
  }

  /// 展示下载进度
  void onReceiveProgress(num received, num total) {
    if (total != -1) {
      downloadProgress.value =
          Decimal.parse((received / total).toStringAsFixed(2))
              .toDouble()
              .toPrecision(2);
    }
  }

  /// 检查是否有权限，用于安卓
  Future<bool> checkPermission() async {
    if (await DeviceUtil.getPlatForm() == 'android') {
      // 检查是否有storage权限，没有的话请求权限
      if (await Permission.storage.request().isGranted) {
        return true;
        // PermissionStatus permission = await PermissionHandler()
        //     .checkPermissionStatus(PermissionGroup.storage);
        // if (permission != PermissionStatus.granted) {
        //   Map<PermissionGroup, PermissionStatus> permissions =
        //       await PermissionHandler()
        //           .requestPermissions([PermissionGroup.storage]);
        //   if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
        //     return true;
        //   }
      } else {
        return false;
      }
    }
    return false;
  }

  T getConfigByCode<T>(String code) {
    List<AppConfigItem> items = appConfig.items!;
    dynamic config = items.firstWhereOrNull((element) => element.name == code);
    if (config != null) {
      return config.data as T;
    }
    return '' as T;
  }

  void changeTextScale(bool? value) {
    if (value ?? false) {
      scale(1.2);
    } else {
      scale(1.0);
    }
    isLarge.value = value ?? false;
  }

  Future<void> requestPermission() async {
    // final status = await AppTrackingTransparency.trackingAuthorizationStatus;
    // if (status != TrackingStatus.authorized) {
    //   await Future.delayed(const Duration(seconds: 2));
    //   await AppTrackingTransparency.requestTrackingAuthorization();
    // }
  }
}
