import 'dart:async';

import 'package:fis_common/index.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:fis_ui/base_define/page.dart';
import 'package:fis_ui/index.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/router/index.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/architecture/webapi/services/multipart_upload.dart';
import 'package:flyinsono/managers/interfaces/entities/print_driver_info.dart';
import 'package:flyinsono/managers/interfaces/remote_maintenance.dart';
import 'package:flyinsono/pages/college/widgets/upload_media_library/upload_media_library_web.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/views/desktop/device_live/device_live_list/controller.dart';
import 'package:flyinsono/views/desktop/device_live/device_live_list/controller/upload_controller.dart';
import 'package:get/get.dart';
import 'package:fis_common/event/event_type.dart';
import 'package:fis_theme/theme.dart';
import 'package:universal_html/html.dart' as html;

// 上传打印机页面
class UploadPrinterDriverDialog extends FStatefulWidget implements FPage {
  UploadPrinterDriverDialog({super.key});

  @override
  String get pageName => 'UploadPrinterDriverDialog';

  @override
  FState<FStatefulWidget> createState() {
    return FUploadPrinterDriverState();
  }
}

class FUploadPrinterDriverState extends FState<UploadPrinterDriverDialog> {
  final controller = Get.find<DeviceLiveListDesktopController>();
  final remoteMaintenanceManager = Get.find<IRemoteMaintenanceManager>();
  final uploadController = Get.put(UploadController());
  final FEventHandler<double> onProcessChange = FEventHandler<double>();
  final FEventHandler<void> onCancelUpload = FEventHandler<void>();
  String? _errorMessage;
  bool _checkSuccess = false;

  String? _printerBrands;
  html.File? _file;
  List<String>? _printerModels;

  @override
  void initState() {
    // controller.state.updateFileName = '';
    // controller.state.packageName = '';
    controller.state.adaptSystemVersion = null;
    controller.state.packageName = '';
    controller.state.updateFileName = '';
    remoteMaintenanceManager.onCheckPrintDriverStateChange
        .addListener(_onCheckPrintDriverStateChange);
    super.initState();
  }

  @override
  void dispose() {
    remoteMaintenanceManager.onCheckPrintDriverStateChange
        .removeListener(_onCheckPrintDriverStateChange);
    super.dispose();
  }

  @override
  FWidget build(BuildContext context) {
    return FSimpleDialog(
      contentPadding: EdgeInsets.symmetric(vertical: 25, horizontal: 25),
      title: FText(
        i18nBook.laboratory.upload.t,
        style: TextStyle(
          color: Colors.white,
          fontSize: 18,
        ),
      ),
      onClose: () {
        router.back();
      },
      okString: i18nBook.common.confirm.t,
      cancelString: i18nBook.common.cancel.t,
      children: [
        FContainer(
          width: 550,
          margin: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
          child: FColumn(
            children: [
              _buildUploadRow(
                i18nBook.remoteControl.localPrinterDriverFile.t,
                _buildUpload(),
                true,
              ),
              _buildUploadRow(
                i18nBook.remoteControl.printerDriverName.t,
                _buildInput(
                  onChanged: (value) {
                    controller.state.packageName = value;
                  },
                  textInput: controller.state.packageName,
                ),
                true,
              ),
              _buildUploadRow(
                i18nBook.remoteControl.adaptSystemVersion.t,
                _buildSingleSelect(),
              ),
              const FSizedBox(height: 10),
              if (_errorMessage.isNotNullOrEmpty) ...[
                FText(
                  _errorMessage!,
                  style: TextStyle(color: Colors.red),
                ),
              ]
            ],
          ),
        ),
      ],
      isDefault: false,
      bottomButton: FContainer(
        padding: EdgeInsets.symmetric(vertical: 10),
        child: FRow(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _buildCommonButton(i18nBook.common.submit.t, _submitPrintDriver),
          ],
        ),
      ),
    );
  }

  /// 上传单行
  FWidget _buildUploadRow(
    String label,
    FWidget value, [
    bool isRequired = false,
  ]) {
    final labelStyle = TextStyle(fontSize: 16);

    FWidget txt = FText.rich(
      TextSpan(
        children: [
          TextSpan(
            text: label,
            style: labelStyle,
          ),
          isRequired
              ? TextSpan(
                  text: ' *',
                  style: labelStyle.copyWith(color: Colors.red),
                )
              : TextSpan(),
        ],
      ),
    );

    return FContainer(
      margin: EdgeInsets.symmetric(
        vertical: 10,
      ),
      child: FRow(
        children: [
          FContainer(
            width: 160,
            child: txt,
          ),
          value,
        ],
      ),
    );
  }

  FWidget _buildCommonButton(String buttonName, VoidCallback onPressed) {
    return FElevatedButton(
      child: FText(buttonName),
      onPressed: () {
        onPressed.call();
      },
      businessParent: this.widget,
      name: buttonName,
      style: ElevatedButton.styleFrom(
        elevation: 0,
        padding: EdgeInsets.symmetric(
          vertical: 15,
          horizontal: 25,
        ),
      ),
    );
  }

  /// 输入框
  FWidget _buildInput({
    bool readOnly = false,
    VoidCallback? onTap,
    String? textInput,
    ValueCallback? onChanged,
  }) {
    return FBorderInput(
      hintSize: 16,
      contentSize: 16,
      maxLength: 20,
      borderColor: Color.fromRGBO(234, 234, 234, 1),
      height: 38,
      readOnly: readOnly,
      hintText: '',
      onTap: onTap,
      inputFormatters: [
        FilteringTextInputFormatter.allow(
            RegExp(r'[\u4e00-\u9fa5A-Za-z0-9]')) // 允许字母、数字和中文
      ],
      onChanged: (value) {
        onChanged?.call(value);
      },
      controller: TextEditingController(
        text: textInput,
      ),
    );
  }

  /// 单选框
  FWidget _buildSingleSelect() {
    final select = FObx(
      () => FSelect<FSelectOptionModel, String>(
        source: controller.state.printerSystemList,
        hintText: i18nBook.remoteControl.adaptSystemVersion.t,
        value: controller.state.adaptSystemVersion,
        height: 36,
        fontFamily: FTheme.ins.localeSetting.fontFamily,
        optionLabelExtractor: (data) => data.title,
        optionValueExtractor: (data) => data.value,
        onSelectChanged: (value, index) {
          controller.state.adaptSystemVersion = value;
        },
      ),
    );
    return FExpanded(child: select);
  }

  FWidget _buildUpload() {
    return FExpanded(
      child: FRow(
        children: [
          FObx(
            () => _buildInput(
              readOnly: true,
              textInput: controller.state.updateFileName,
            ),
          ),
          FContainer(
            margin: EdgeInsets.only(left: 10),
            child: _buildCommonButton(
              i18nBook.common.add.t,
              () async {
                final fileTypes = [
                  '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;
                String filePath = '';
                if (files != null && files.isNotEmpty) {
                  filePath = files[0].name;
                  _file = files[0];
                  await uploadController.shellSelectFile(filePath);
                }
              },
            ),
          )
        ],
      ),
    );
  }

  void _onCheckPrintDriverStateChange(Object sender, PrintDriverInfo e) {
    print('_onCheckPrintDriverStateChange $e');

    switch (e.state ?? CheckPrintDriverState.Success) {
      case CheckPrintDriverState.Success:
        _errorMessage = '';
        _checkSuccess = true;
        _printerBrands = e.printerBrands;
        _printerModels = e.printerModels;
        break;
      case CheckPrintDriverState.LargeFile:
        setState(() {
          _errorMessage = i18nBook.remoteControl.fileTooLarge.t;
        });
        break;
      case CheckPrintDriverState.VerificationFailed:
        setState(() {
          _errorMessage = i18nBook.remoteControl.validationFailed.t;
        });
        break;
      case CheckPrintDriverState.Failed:
        setState(() {
          _errorMessage = i18nBook.remoteControl.verificationFailed.t;
        });
        break;
      case CheckPrintDriverState.Ready:
        controller.state.updateFileName = e.fileName ?? '';
        setState(() {
          _errorMessage = '';
        });
        break;
    }
  }

  Future<void> _submitPrintDriver({int retryTimes = 0}) async {
    if (!_checkSuccess) {
      _errorMessage = i18nBook.remoteControl.validationFailed.t;
      return;
    }
    if (controller.state.updateFileName.isNullOrEmpty ||
        controller.state.packageName.isNullOrEmpty) {
      PromptBox.toast(i18nBook.user.fullFillRequirements.t);
      return;
    }
    var isValidDeviceDriverName = await rpc.device.existsDevicePrinterAsync(
        ExistsDevicePrinterRequest(
            name: controller.state.packageName, token: Store.user.token));
    if (isValidDeviceDriverName) {
      PromptBox.toast(i18nBook.remoteControl.existDriverName.t);
      return;
    }

    router.back();
    router.dialog(
      () => ShowProgressCircle(
        onProcessChange,
        onCancel: () {
          router.back();
          onCancelUpload.emit(this, null);
        },
      ),
      dismissible: false,
    );
    if (_file != null)
      await _multipartUpload(
        _file!,
        onCancelUpload: onCancelUpload,
      );
  }

  Future<bool> _multipartUpload(
    html.File file, {
    FEventHandler<void>? onCancelUpload,
  }) async {
    // 创建一个Completer
    final completer = Completer<bool>();
    await rpc.storage.multipartUpload(
      file,
      (v) {
        onProcessChange.emit(this, v);
      },
      onCancelUpload,
    ).then((value) async {
      var packageName = controller.state.packageName;
      List<UploadDeviceFileInfoDTO> fileUploadInfoList = [
        UploadDeviceFileInfoDTO(
          partNum: 0,
          fileUrl: value,
        ),
      ];
      await rpc.device.addDevicePrinterAsync(
        AddDevicePrinterRequest(
          name: packageName,
          osVersion: controller.state.adaptSystemVersion,
          fileUploadInfoList: fileUploadInfoList,
          fileSize: file.size,
          printerBrands: _printerBrands,
          printerModels: _printerModels,
          token: Store.user.token,
        ),
      );
      controller.findPrintDriverDatas();
    });
    // 返回completer的Future对象
    return completer.future;
  }
}
