import 'dart:async';

import 'package:fis_common/logger/logger.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:flutter/foundation.dart';
import 'package:flyinsono/architecture/webapi/services/large_file_uploader.dart';
import 'package:flyinsono/pages/college/widgets/upload_media_library/upload_media_library_web.dart';
import 'package:universal_html/html.dart' as html;
import 'package:fis_common/event/event_type.dart';

extension StorageServiceExt on StorageService {
  ///分片上传
  Future<String> multipartUpload(
    html.File file,
    void Function(double)? onProcessChange,
    FEventHandler<void>? onCancelUpload,
  ) async {
    bool isCancel = false;
    FEventCallback<void> _onCancel = (sender, e) => isCancel = true;
    onCancelUpload?.addListener(_onCancel);
    final fileSize = file.size;
    final fileName = file.name;
    double _processValue = 0;

    // 计算所需的分片数量
    final totalChunksCount = (fileSize / chunkSize).ceil();
    var uploadId = await initiateMultipartUpload(fileName);
    var auth = await getAuth(
      fileName: fileName,
      isRechristen: false,
      urlParams: [
        DataItemDTO(
          key: 'uploadId',
          value: uploadId,
        ),
      ],
    );
    List<PartInfo> uploadedPartInfos = [];
    int taskCount = 0;
    List<Future<PartInfo?>> tasks = []; //上传任务列表
    Map<int, double> processValues = {};
    for (var i = 0; i < totalChunksCount; i++) {
      if (isCancel) {
        onCancelUpload?.removeListener(_onCancel);
        return '';
      }
      final completer = Completer<PartInfo?>();
      Future<PartInfo?> uploadItem() async {
        if (isCancel) {
          onCancelUpload?.removeListener(_onCancel);
          return null;
        }
        var partInfo = await uploadItemPart(
          i,
          totalChunksCount,
          fileSize,
          file,
          auth: auth,
          partFileTotalCount: totalChunksCount,
          uploadId: uploadId,
          partFileName: fileName,
          onProcessChange: (v) {
            if (isCancel) {
              onCancelUpload?.removeListener(_onCancel);
              return null;
            }
            processValues[i] = v;
            double sum = processValues.values.reduce((a, b) => a + b);
            _processValue = 0.01 + (sum * 0.98) / totalChunksCount;
            if (kDebugMode) {
              logger.i('进度更新：$_processValue');
            }
            if (_processValue < 0.99) {
              onProcessChange?.call(_processValue);
            }
          },
          checkCancel: () => isCancel,
        );
        return partInfo;
      }

      var task = uploadItem();
      task.then((partInfo) {
        if (isCancel) {
          onCancelUpload?.removeListener(_onCancel);
          return '';
        }
        taskCount--;
        completer.complete(partInfo);
        if (partInfo != null) {
          uploadedPartInfos.add(partInfo);
        }
      });
      tasks.add(completer.future);
      taskCount++;
      // 控制上传并发数
      while (taskCount >= 5) {
        await Future.wait(tasks);
      }
      if (i == totalChunksCount - 1) {
        await Future.wait(tasks);
      }
    }
    if (isCancel) {
      onCancelUpload?.removeListener(_onCancel);
      return '';
    }
    var url =
        await completeMultipartUpload(fileName, uploadId, uploadedPartInfos);
    onProcessChange?.call(1);
    return url ?? '';
  }

  /// 云点播上传
  Future<TcVod> vodUpload(
    html.File file,
    FEventHandler<void>? onCancelUpload,
  ) async {
    // 云点播
    final getSignature = await getVodAuthorizationAsync();
    getSignatureFunction() {
      return getSignature;
    }

    TcVod tcVod = TcVod(getSignatureFunction, file);
    FEventCallback<void> _onCancel = (sender, e) {
      tcVod.cancelUpload();
    };
    onCancelUpload?.addListener(_onCancel);
    tcVod.addMediaUploadResumeListener(() {
      tcVod.resumeUpload();
      print('断点续传恢复');
    });

    return tcVod;
  }
}
