import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/lab/manager/interfaces/task.dart';
import 'package:flyinsono/lab/mock_data/mock_rpc.dart';
import 'package:flyinsono/lab/pages/lab_export/entitys/image_type.dart';
import 'package:flyinsono/managers/interfaces/entities/process_arg.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:fis_common/logger/logger.dart';
import 'interfaces/entities/export_data.dart';
import 'interfaces/entities/task_info.dart';
import 'interfaces/export_data.dart';
import 'interfaces/shell_io_task_manager.dart';
import 'package:fis_common/index.dart';
import 'package:fis_common/event/event_type.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:fis_common/helpers/encrypt.dart';

class ExportDataManager extends ShellIOTaskManager
    implements IExportDataManager {
  @override
  String get taskId => super.taskId;

  /// 用户登录令牌
  String get token => Store.user.token;

  FEventHandler<ExportProcessArg> get processChange => super.processChange;

  final vidImageTypes = [
    SampleRemedicalFileDataTypeEnum.ThirdVidMovie,
    SampleRemedicalFileDataTypeEnum.ThirdVidSingle,
    SampleRemedicalFileDataTypeEnum.VinnoVidSingle,
    SampleRemedicalFileDataTypeEnum.VinnoVidMovie
  ];
  final imageTypes = [
    SampleRemedicalFileDataTypeEnum.MeasurementImage,
    SampleRemedicalFileDataTypeEnum.Image,
    SampleRemedicalFileDataTypeEnum.AnalysisImage,
  ];

  @override
  Future<String> exportDatas(
    String name,
    String? path, {
    ExportImageFormat? exportImageFormat,
    required String businessCode,
    required ProjectSampleDataExportResult sampleDataInfo,
  }) async {
    try {
      if (super.status == VTaskStatus.Processing) {
        PromptBox.toast("当前已有导出任务正在进行中！");
        return "";
      }
      processChange.removeListener(onProcessChange);
      startTime = DateTime.now();
      endTime = null;
      datas.clear();
      status = VTaskStatus.Processing;
      DateFormat formatter = DateFormat('yyyy-MM-dd-HH:mm:ss');
      String formattedDate = formatter.format(DateTime.now());
      List<SampleDetailInfo> sampleDetailList =
          sampleDataInfo.sampleDetailList ?? [];

      String exportExcelUrl = sampleDataInfo.exportExcelUrl ?? '';
      if (exportExcelUrl.isNotEmpty) {
        int lastSlashIndex = exportExcelUrl.lastIndexOf('/');
        // 提取文件名
        String fileNameWithExtension =
            exportExcelUrl.substring(lastSlashIndex + 1);

        // 找到最后一个点的位置
        int lastDotIndex = fileNameWithExtension.lastIndexOf('.');

        // 去掉文件后缀
        String fileId = (lastDotIndex == -1)
            ? fileNameWithExtension
            : fileNameWithExtension.substring(0, lastDotIndex);
        datas.add(ExportDataItem(
          fileId,
          exportExcelUrl,
          'xlsx',
          (sampleDataInfo.name ?? '') + "测量数据",
        ));
      }
      for (SampleDetailInfo sampleDetailInfo in sampleDetailList) {
        var sampleRemedicalBasicList =
            sampleDetailInfo.sampleRemedicalBasicList ?? [];
        if (sampleRemedicalBasicList.isEmpty) {
          continue;
        }
        List<DataItemDTO> patientInfos = sampleDetailInfo.patientInfo ?? [];
        String patientName = patientInfos
                .firstWhereOrNull((element) =>
                    element.key == "Name" || element.key == "AnimalInfoName")
                ?.value ??
            '';
        patientName = FEncryptHelper.decryptBase64(patientName);
        for (SampleRemedicalBasicInfo sampleRemedicalBasicInfo
            in sampleRemedicalBasicList) {
          String examDate = sampleRemedicalBasicInfo.remedicalName ?? '';
          var sampleRemedicalInfoList =
              sampleRemedicalBasicInfo.sampleRemedicalInfoList ?? [];
          int index = 1;
          for (SampleRemedicalInfoDTO sampleRemedicalInfoDTO
              in sampleRemedicalInfoList) {
            String fileExtentName = ".jpg";
            SampleRemedicalFileDataTypeEnum fileType =
                sampleRemedicalInfoDTO.fileDataType;
            if (vidImageTypes.contains(fileType)) {
              fileExtentName = 'vid';
            } else if (imageTypes.contains(fileType)) {
              fileExtentName = 'jpg';
            } else if (fileType ==
                SampleRemedicalFileDataTypeEnum.AnalysisVideo) {
              fileExtentName = "mp4";
            }
            String fileNameNoExtName =
                patientName + "_" + examDate + "_" + index.toString();
            datas.add(ExportDataItem(
              sampleRemedicalInfoDTO.businessCode ?? '',
              sampleRemedicalInfoDTO.imageUrl ?? '',
              fileExtentName,
              fileNameNoExtName,
            ));
            index++;
          }
        }
      }
      super.taskName = (sampleDataInfo.name ?? '') +
          "数据导出_" +
          formattedDate +
          "-" +
          "(${datas.length})";
      var taskDetailList = datas
          .map((e) => CreateTaskDetailInfo(
                id: e.id,
                name: e.name,
                description: '',
              ))
          .toList();

      super.taskId = await Get.find<IServerTaskManager>().createTask(
        businessCode: businessCode,
        taskDetailList: taskDetailList,
        name: taskName,
      );
      print("ExportDataManager task id:$taskId");
      processChange.addListener(onProcessChange);
      String sampleDataInfoJson = jsonEncode(sampleDataInfo.toJson());
      rpc.platform.exportSampleDatas(
          sampleDataInfoJson,
          name,
          path ?? '',
          exportImageFormat?.imageType.toString() ?? '',
          exportImageFormat?.videoType.toString() ?? '');
      return taskId;
    } catch (e) {
      logger.e('ExportDataManager exportDatas ex:', e);
    }
    return "";
  }

  @override
  Future<List<UDiskDriveInfoDTO>> getExternalStorageList() async {
    List<UDiskDriveInfoDTO> result = [];
    try {
      result = await rpc.platform.getUDiskDriveInfo();
    } catch (e) {
      logger.e("ImportExportDataManager getExternalStorageList ex:", e);
    }
    return result;
  }

  @override
  Future<List<UDiskDriveInfoDTO>> getAllStorageList() async {
    List<UDiskDriveInfoDTO> result = [];
    try {
      result = await rpc.platform.getAllStorageList();
    } catch (e) {
      logger.e("ImportExportDataManager getExternalStorageList ex:", e);
    }

    return result;
  }

  @override
  TaskInfo? getTaskInfo(String taskId) {
    if (taskId != taskId) {
      return null;
    }
    DateFormat formatter = DateFormat('yyyy-MM-dd HH:mm:ss');
    String formattedDate = formatter.format(startTime);
    Duration difference;
    if (endTime == null) {
      difference = DateTime.now().difference(startTime);
    } else {
      difference = endTime!.difference(startTime);
    }

    // 提取分钟和秒钟
    int minutes = difference.inMinutes;
    int seconds = difference.inSeconds % 60;
    String elapsedTime = '${minutes}min${seconds}s';
    return TaskInfo(
        title: "数据导出中",
        startTime: formattedDate,
        complateCount: datas.where((element) => element.progress == 1).length,
        totalCount: datas.length,
        elapsedTime: elapsedTime,
        patientCode: "");
  }

  @override
  TaskBaseDTO? getCurrentTask() {
    if (datas.isEmpty ||
        taskId.isNullOrEmpty ||
        status == VTaskStatus.Completed) {
      return null;
    }
    DateFormat formatter = DateFormat('yyyy-MM-dd-HH:mm');
    String formattedDate = formatter.format(DateTime.now());
    return TaskBaseDTO(
      taskName: "数据导出-$formattedDate(${datas.length})",
      code: taskId,
      status: status,
      taskType: VTaskType.UserExport,
    );
  }

  @override
  Future<void> cancelExport() async {
    try {
      processChange.removeListener(onProcessChange);
      cancelTask();
      taskId = "";
      status = VTaskStatus.Canceled;
      return await rpc.platform.cancelExport();
    } catch (e) {
      logger.e("ExportDataManager cancelExport ex:", e);
    }
  }

  @override
  List<TaskDetail> getLocalTasks(String currentSelectedTaskId) {
    return super.getLocalTasks(currentSelectedTaskId);
  }

  @override
  Future<ProjectSampleDataExportResult> getProjectSampleDataExport(
      String projectCode, List<String> patientCodes) async {
    return await rpc.researchEdition.getProjectSampleDataExportAsync(
      GetProjectSampleDataExportRequest(
        token: token,
        projectCode: projectCode,
        patientCodes: patientCodes,
      ),
    );
  }
}
