import 'dart:async';
import 'dart:convert';

import 'package:fis_common/event/event_type.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_theme/theme.dart';
import 'package:fis_ui/base_define/page.dart';
import 'package:fis_ui/index.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/router/index.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/architecture/webapi/services/multipart_upload.dart';
import 'package:flyinsono/managers/interfaces/entities/media_library.dart';
import 'package:flyinsono/pages/college/controller.dart';
import 'package:flyinsono/pages/college/widgets/media_librarys_card.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/views/common/device_live/device_live_list/widgets/progress_circle.dart';
import 'package:get/get.dart';
import 'package:universal_html/html.dart' as html;
// import 'dart:js';
import 'package:universal_html/js.dart' as js;
import 'package:fis_common/logger/logger.dart';

class UploadMediaLibrary extends FStatefulWidget implements FPage {
  @override
  FState<FStatefulWidget> createState() => _UploadMediaLibraryState();

  @override
  String get pageName => 'UploadMediaLibrary';
}

class _UploadMediaLibraryState extends FState<UploadMediaLibrary> {
  final controller = Get.find<FlyinsonoCollegeController>();
  final FEventHandler<double> onProcessChange = FEventHandler<double>();
  final FEventHandler<void> onCancelUpload = FEventHandler<void>();
  List<MediaLibrary> _uploadFiles = [];
  @override
  void initState() {
    super.initState();
  }

  @override
  FWidget build(BuildContext context) {
    return FSimpleDialog(
      okString: i18nBook.common.confirm.t,
      cancelString: i18nBook.common.cancel.t,
      isDefault: true,
      title: FText(
        i18nBook.college.uploadMaterial.t,
        style: TextStyle(color: Colors.white),
      ),
      contentPadding: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
      onCancel: () => router.back(),
      onOk: () {
        if (_uploadFiles.isNotEmpty) {
          controller.submitMediaLibrary(_uploadFiles);
        }
        router.back();
      },
      onClose: () => router.back(),
      children: [
        _buildUploadView(),
      ],
    );
  }

  FWidget _buildUploadView() {
    List<FWidget> children = [_buildUploadButton()];
    children.addAll(_uploadFiles
        .map(
          (e) => MediaLibrarysCard(
            e,
            size: 120,
          ),
        )
        .toList());
    return FContainer(
      width: 800,
      height: 400,
      child: FSingleChildScrollView(
        child: FWrap(
          spacing: 15,
          runSpacing: 15,
          children: children,
        ),
      ),
    );
  }

  FWidget _buildUploadButton() {
    return FInkWell(
      onTap: () async {
        final fileTypes = [
          'video/mp4',
          'application/pdf',
          'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
          'application/vnd.openxmlformats-officedocument.presentationml.presentation',
          'image/jpeg',
          'image/png',
          'application/zip',
          'application/x-zip-compressed',
          'application/x-7z-compressed',
          'application/x-rar-compressed'
        ];
        final fileInput = html.FileUploadInputElement()
          ..accept = fileTypes.join(',')
          ..multiple = true; // 设置支持的文件类型
        fileInput.click(); // 打开文件选择器
        await fileInput.onChange.first;
        final files = fileInput.files;
        if (files != null) {
          bool allFilesValid = true;

          for (int i = 0; i < files.length; i++) {
            if (!fileTypes.contains(files[i].type)) {
              allFilesValid = false;
              break;
            }
          }
          if (allFilesValid) {
            router.dialog(
              () => ShowProgressCircle(
                onProcessChange,
                onCancel: () {
                  router.back();
                  onCancelUpload.emit(this, null);
                },
              ),
              dismissible: false,
            );
            for (int i = 0; i < files.length; i++) {
              if (_isVideoMimeType(files[i].type)) {
                // 云点播上传
                await _videoVodUpload(
                  files[i],
                  files.length,
                  i + 1,
                  onCancelUpload,
                );
              } else {
                // 大文件分片上传
                await _multipartUpload(
                  files[i],
                  files.length,
                  i + 1,
                  onCancelUpload: onCancelUpload,
                );
              }
            }
          } else {
            PromptBox.toast(i18nBook.upload.uploadFailedUnsupportedFileType.t);
          }
        }
      },
      child: FContainer(
        width: 120,
        height: 120,
        decoration: BoxDecoration(
          border: Border.all(color: FTheme.ins.colorScheme.primary),
          borderRadius: BorderRadius.all(Radius.circular(8)),
        ),
        child: FIcon(
          Icons.add,
          color: FTheme.ins.colorScheme.primary,
        ),
      ),
    );
  }

  Future<bool> _videoVodUpload(
    html.File? file,
    int fileLength,
    int currentIndex,
    FEventHandler<void>? onCancelUpload,
  ) async {
    // 创建一个Completer
    final completer = Completer<bool>();

    // 云点播上传
    TcVod vodUpload = await rpc.storage.vodUpload(file!, onCancelUpload);
    vodUpload.addMediaProgressListener((double progress) {
      double totalProgress =
          ((currentIndex - 1) / fileLength) + ((1 / fileLength) * progress);
      // 更新进度条
      onProcessChange.emit(
        this,
        totalProgress,
      );
    });
    vodUpload.onDone((p0) async {
      var currentVod = jsonDecode(p0);
      var fileName = file.name;
      var addResult = await controller.addMediaLibrary(
        fileName,
        currentVod['url']!,
        currentVod['fileId']!,
      );
      var fileType = controller.getFileTypeEnum(fileName);
      if (addResult) {
        setState(() {
          _uploadFiles.add(
            MediaLibrary(
              name: fileName,
              fileType: fileType,
              fileToken: currentVod['url']!,
            ),
          );
        });
      }

      // 完成上传时，设置completer完成状态并返回结果
      completer.complete(addResult);
    });

    // 返回completer的Future对象
    return completer.future;
  }

  Future<bool> _multipartUpload(
    html.File? file,
    int fileLength,
    int currentIndex, {
    FEventHandler<void>? onCancelUpload,
  }) async {
    // 创建一个Completer
    final completer = Completer<bool>();
    await rpc.storage.multipartUpload(
      file!,
      (v) {
        double totalProgress =
            ((currentIndex - 1) / fileLength) + ((1 / fileLength) * v);
        onProcessChange.emit(this, totalProgress);
      },
      onCancelUpload,
    ).then((result) async {
      if (result.isNotEmpty) {
        logger.i('UploadMediaLibrary result:result');
        var fileName = file.name;
        var addResult = await controller.addMediaLibrary(fileName, result);
        var fileType = controller.getFileTypeEnum(fileName);
        // 完成上传时，设置completer完成状态并返回结果
        completer.complete(addResult);
        if (addResult) {
          setState(() {
            _uploadFiles.add(
              MediaLibrary(
                name: fileName,
                fileType: fileType,
                fileToken: result,
              ),
            );
          });
        }
      }
    });
    // 返回completer的Future对象
    return completer.future;
  }

  bool _isVideoMimeType(String mimeType) {
    return mimeType.startsWith('video/');
  }
}

class ShowProgressCircle extends FStatefulWidget {
  final FEventHandler<double> onProcessChange;
  final void Function()? onCancel;
  final String? hintText;

  ShowProgressCircle(this.onProcessChange, {this.onCancel, this.hintText});
  @override
  FState<FStatefulWidget> createState() {
    return _ShowProgressCircleState();
  }
}

class _ShowProgressCircleState extends FState<ShowProgressCircle> {
  double _progress = 0;
  bool _isBack = false;
  @override
  void initState() {
    widget.onProcessChange.addListener(_onProcessChange);
    super.initState();
  }

  @override
  void didUpdateWidget(ShowProgressCircle oldWidget) {
    if (_progress < 1) {
      setState(() {});
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    widget.onProcessChange.removeListener(_onProcessChange);
    super.dispose();
  }

  @override
  FWidget build(BuildContext context) {
    return QuickFWidget(
      ProgressCircle(
        progress: _progress,
        onCancel: widget.onCancel,
        hintText: widget.hintText ?? i18nBook.college.uploadProgress.t,
      ),
    );
  }

  void _onProcessChange(Object sender, double e) {
    setState(() {
      _progress = e;
    });
    if (_progress == 1) {
      if (!_isBack) {
        //_isBack防止重复触发
        _isBack = true;
        router.back();
      }
    }
  }
}

// 云点播
class TcVod {
  final js.JsObject _uploader;

  TcVod(Function getSignature, dynamic fileRaw)
      : _uploader = js.context.callMethod('createTcVodInstance', [
          getSignature,
          fileRaw,
        ]) as js.JsObject;

  // 添加您需要实现的功能和对应的方法，例如：
  void addMediaProgressListener(Function(double) listener) {
    js.context.callMethod('addMediaProgressListener', [
      _uploader,
      js.allowInterop((double progress) {
        listener(progress);
      }),
    ]);
  }

  void onDone(Function(String) listener) {
    js.context.callMethod('onDone', [
      _uploader,
      js.allowInterop((String fileObj) {
        listener(fileObj);
      }),
    ]);
  }

  void addMediaUploadResumeListener(Function() listener) {
    js.context.callMethod('addMediaUploadResumeListener', [
      _uploader,
      js.allowInterop(listener),
    ]);
  }

  void cancelUpload() {
    js.context.callMethod('cancelUpload', [_uploader]);
  }

  void resumeUpload() {
    js.context.callMethod('resumeUpload', [_uploader]);
  }
}
