import 'dart:convert';

import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/pages/remedical/consultation/controller.dart';
import 'package:flyinsono/pages/remedical/consultation/state.dart';
import 'package:flyinsono/utils/export_status_type.dart';
import 'package:flyinsono/rpc.dart';
import 'package:fis_jsonrpc/utils.dart';
import 'package:fis_common/index.dart';
import 'package:intl/intl.dart';
import 'package:fis_common/helpers/encrypt.dart';

class ExportController {
  late ConsultationController controller;
  late FConsultationState state;
  ExportController(ConsultationController controller) {
    this.controller = controller;
    this.state = controller.state;
  }

  ///导出
  Future<void> export() async {
    var patientCode = controller.state.patientCode;
    var isExportReport = state.selectedExportItems.contains(0);
    var isExportRemedicalData = state.selectedExportItems.contains(2);

    var exportDataPara = new ExportRemedicalDataRequest(
      token: Store.user.token,
      startTime: state.startDateTime,
      endTime:
          state.endDateTime.add(Duration(hours: 23, minutes: 59, seconds: 59)),
      isExportReport: state.selectedExportItems.contains(0),
      isExportRecord: true,
      isExportRemedicalData: state.selectedExportItems.contains(2),
      patientCodes: [patientCode],
      languageCode: i18nBook.locale.toCodeString('-'),
    );
    bool isReportListEmpty = true;
    bool isRemedicalListEmpty = true;
    var dataToExport =
        await rpc.remedical.exportRemedicalDataAsync(exportDataPara);
    if ((dataToExport.reportList?.isNotEmpty ?? false) &&
        (dataToExport.reportList?.first.reportItemList?.isNotEmpty ?? false)) {
      isReportListEmpty = false;
    }

    if ((dataToExport.remedicalList?.isNotEmpty ?? false) &&
        (dataToExport.remedicalList?.first.remedicalItemList?.isNotEmpty ??
            false)) {
      isRemedicalListEmpty = false;
    }
    if (isExportReport &&
        isExportRemedicalData &&
        isReportListEmpty &&
        isRemedicalListEmpty) {
      PromptBox.toast(i18nBook.errorCodes.errorCode4056.t);
      return;
    } else if (isExportReport && !isExportRemedicalData && isReportListEmpty) {
      PromptBox.toast(i18nBook.errorCodes.errorCode4056.t);
      return;
    } else if (isExportRemedicalData &&
        !isExportReport &&
        isRemedicalListEmpty) {
      PromptBox.toast(i18nBook.errorCodes.errorCode4056.t);
      return;
    } else if (!isExportRemedicalData && !isExportReport) {
      PromptBox.toast(i18nBook.errorCodes.errorCode4056.t);
      return;
    }

    state.exportProgress = 0.0;
    state.exportState = ExportStatusType.Downloading;
    state.isExporting = true;
    var exportJsonData = jsonEncode({
      "reportList": fromReportDataList(dataToExport.reportList),
      "remedicalList": dataToExport.remedicalList,
      "exportItems": state.selectedExportItems,
      "subFolders": _generateSubFolderName(),
    });
    print(exportJsonData);
    await rpc.platform.exportPatientZipFile(exportJsonData, "test.zip");
  }

  List<ReportDataWithFileName> fromReportDataList(List<ReportData>? list) {
    if (list == null) {
      return [];
    }
    return list.map((e) => ReportDataWithFileName.fromReportData(e)).toList();
  }

  List<String> _generateSubFolderName() {
    var subFolderList = <String>[];
    var patientName = controller.state.patientInfo.visibleName ?? '';
    if (patientName.isNotNullOrEmpty) {
      subFolderList.add("($patientName)");
    }
    if (state.selectedExportItems.contains(0)) {
      subFolderList.add(i18nBook.remedical.examReport.t);
    }
    if (state.selectedExportItems.contains(2)) {
      subFolderList.add(i18nBook.remedical.scanImage.t);
    }

    return subFolderList;
  }
}

class ReportDataWithFileName extends ReportData {
  List<ReportItemWithFileName>? reportItemWithFileNameList;

  ReportDataWithFileName({
    String? patientName,
    String? patientCode,
    this.reportItemWithFileNameList,
  }) : super(
          patientName: patientName,
          patientCode: patientCode,
        );

  factory ReportDataWithFileName.fromReportData(ReportData data) {
    List<ReportItemWithFileName>? reportItemListWithFileName;
    if (data.reportItemList != null) {
      reportItemListWithFileName = data.reportItemList!
          .map((e) =>
              ReportItemWithFileName.fromReportItem(e, data.patientName ?? ""))
          .toList();
    }
    return ReportDataWithFileName(
      patientName: data.patientName,
      patientCode: data.patientCode,
      reportItemWithFileNameList: reportItemListWithFileName,
    );
  }

  Map<String, dynamic> toJson() {
    final map = Map<String, dynamic>();
    if (patientName != null) {
      map['PatientName'] = patientName;
    }
    if (patientCode != null) {
      map['PatientCode'] = patientCode;
    }
    if (reportItemWithFileNameList != null) {
      map['ReportItemList'] = reportItemWithFileNameList;
    }
    return map;
  }
}

class ReportItemWithFileName extends ReportItem {
  String? fileName;

  ReportItemWithFileName({
    String? recordCode,
    String? reportCode,
    String? fileToken,
    DateTime? reportTime,
    DateTime? createTime,
    this.fileName,
  }) : super(
          recordCode: recordCode,
          reportCode: reportCode,
          fileToken: fileToken,
          reportTime: reportTime,
          createTime: createTime,
        );

  factory ReportItemWithFileName.fromReportItem(
      ReportItem item, String patientName) {
    DateFormat format = DateFormat("yyyMMddHHmmss");
    // 读取文件名后缀
    String suffix = "";
    // 获取报告时间
    String reportTimeStr = "";
    if (item.fileToken != null) {
      suffix = item.fileToken!.split(".").last;
    }
    if (item.reportTime != null) {
      reportTimeStr = format.format(item.reportTime!.toLocal());
    }
    String fileName =
        "[$patientName]-[$reportTimeStr]-[${item.reportCode}].$suffix";
    String safeFileName = fileName.replaceAll(RegExp(r'[\\/:*?"<>|]'), 'x');
    return ReportItemWithFileName(
      recordCode: item.recordCode,
      reportCode: item.reportCode,
      fileToken: item.fileToken,
      createTime: item.createTime,
      reportTime: item.reportTime,
      fileName: safeFileName,
    );
  }

  Map<String, dynamic> toJson() {
    final map = Map<String, dynamic>();
    if (recordCode != null) {
      map['RecordCode'] = recordCode;
    }
    if (reportCode != null) {
      map['ReportCode'] = reportCode;
    }
    if (fileToken != null) {
      map['FileToken'] = fileToken;
    }
    if (createTime != null) {
      map['CreateTime'] = JsonRpcUtils.dateFormat(createTime!);
    }
    if (fileName != null) {
      map['FileName'] = fileName;
    }
    return map;
  }
}
