import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/router/desktop/names.dart';
import 'package:flyinsono/architecture/services/modules/config_language.dart';
import 'package:flyinsono/architecture/utils/common_util.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/lab/color/lab_colors.dart';
import 'package:flyinsono/lab/components/classify_data_selector/classify_data_selector.dart';
import 'package:flyinsono/lab/components/lab_dialog.dart';
import 'package:flyinsono/lab/manager/interfaces/project.dart';
import 'package:flyinsono/lab/manager/page_manager.dart';
import 'package:flyinsono/lab/mixin/tab_hook_mixin.dart';
import 'package:flyinsono/lab/mock_data/mock_rpc.dart';
import 'package:flyinsono/lab/pages/lab_batch_analysis/controller.dart';
import 'package:flyinsono/lab/pages/lab_image/index.dart';
import 'package:flyinsono/lab/router/lab_route_names.dart';
import 'package:fis_jsonrpc/services/index.dart';
import 'package:flyinsono/managers/interfaces/language.dart';
import 'package:get/get.dart';
import 'package:fis_measure/configs/patient.dart';
import 'package:fis_measure/interfaces/enums/species.dart';
import 'package:fis_common/helpers/encrypt.dart';
import 'index.dart';

class LabDataController extends GetxController with TabHookMixin {
  LabDataController({
    required this.tabHashCode,
  });
  @override
  final int tabHashCode;

  final state = LabDataState();

  /// 数据页分为以下五个部分
  static const dataSourceSelectorId = "data_source_selector"; // 数据源选择器
  static const patientListId = "patient_list"; // 病人/样本列表
  static const recordListId = "record_list"; // 检查记录列表
  static const imageListId = "image_list"; // 图片列表

  /// 数据源
  List<ProjectModel> dataSourceList = [];
  String selectedDataSourceId = "";

  /// 数据源搜索栏输入控制器
  final dataSourceSearchInputController = TextEditingController();

  /// 病人列表
  List<ClassifyData<PatientModel>> patientClassifyData = [];

  final languageConfigManager = Get.find<ILanguageConfigManager>();

  int selectedClassifyIndex = 0;
  int selectedPatientIndex = 0;
  bool isPatientListLoading = false;

  /// 检查记录列表
  List<RecordModel> recordList = [];
  bool isRecordListLoading = false;

  /// 图片列表
  List<ImageModel> imageList = [];
  bool isImageListLoading = false;

  /// 当前项目的病人类型
  OrganizationPatientTypeEnum patientType = OrganizationPatientTypeEnum.Person;

  List<PatientModel> get selectedPatientList =>
      [patientClassifyData[selectedClassifyIndex].data[selectedPatientIndex]];

  // 获取当前选中的病人
  PatientModel get selectedPatient =>
      patientClassifyData[selectedClassifyIndex].data[selectedPatientIndex];

  // 获取当前选中的检查记录
  RecordModel get selectedRecord => recordList[state.selectedRecordIndex];

  /// 通过arguments 获取的病人code
  String patientCodeByArguments = "";

  /// 当前无数据
  // bool get isNoData => dataSourceList.length == 0;

  /// 项目接口
  final projectService = Get.find<IProjectManager>();

  /// 语言服务
  final languageService = Get.find<LanguageService>();

  // 查看/编辑
  void editRecord() {
    print("查看/编辑 $selectedRecord");
    PageManager.ins.openNewTab(
      LabRouteNames.RecordInfo,
      "查看/编辑",
      multiple: false,
      args: selectedRecord,
    );
  }

  // 删除选中的检查记录
  void deleteRecord() async {
    dynamic result = await Get.dialog(
      LabDialog(
        title: "删除检查",
        content: "确定要删除当前所选检查？",
      ),
      barrierColor: LabColors.base100.withOpacity(0.1),
    );
    if (result is bool && result) {
      bool? deleteRecord = await projectService.deleteRecordAsync(
        recordCode: selectedRecord.id,
        projectCode: selectedDataSourceId,
      );
      if (deleteRecord ?? false) {
        await updatePatientList(selectedDataSourceId);
        PromptBox.toast('删除完成');
        print("删除检查记录 $selectedRecord");
      }
    }
  }

  void clickRecordItem(int index) {
    state.selectedRecordIndex = index;
    updateImageList(recordList[index].images);
  }

  void clickPatientItem(int classifyIndex, int index) {
    selectedClassifyIndex = classifyIndex;
    selectedPatientIndex = index;
    updateRecordList(patientClassifyData[classifyIndex].data[index].code);
    update([patientListId]);
  }

  ///删除病人
  Future<void> deleteCurrentPatient() async {
    String patientCode = patientClassifyData[selectedClassifyIndex]
        .data[selectedPatientIndex]
        .code;
    dynamic result = await Get.dialog(
      LabDialog(
        title: "删除样本",
        content: "确定要删除当前所选样本？",
      ),
      barrierColor: LabColors.base100.withOpacity(0.1),
    );
    if (result is bool && result) {
      bool deleteRecord =
          await projectService.deleteSample(selectedDataSourceId, patientCode);
      if (deleteRecord) {
        await updatePatientList(selectedDataSourceId);
        PromptBox.toast('删除完成');
      }
    }
  }

  // 根据病人 Id 选中病人
  void selectPatientByCode(String patientCode) {
    bool isExist = false;
    for (int i = 0; i < patientClassifyData.length; i++) {
      for (int j = 0; j < patientClassifyData[i].data.length; j++) {
        if (patientClassifyData[i].data[j].code == patientCode) {
          selectedClassifyIndex = i;
          selectedPatientIndex = j;
          isExist = true;
          break;
        }
      }
      if (isExist) break;
    }

    if (!isExist) return;
    updateRecordList(patientCode);
    update([patientListId]);
  }

  void clickImage(int index) {
    var currentProject = dataSourceList
        .firstWhereOrNull((element) => element.id == selectedDataSourceId);
    PageManager.ins.openTab(
      LabRouteNames.Image,
      args: LabImageActiveArguments(
        patient: selectedPatient,
        record: selectedRecord,
        images: imageList,
        selectedImageIndex: index,
        patientType: patientType,
        projectCode: currentProject?.id,
      ),
    );
  }

  /// 空图像测试入口
  void debugForEmptyImageList() async {
    final images = await MockRPC.getImageListByRecordId("");
    PageManager.ins.openTab(
      LabRouteNames.Image,
      args: LabImageActiveArguments(
        patient: selectedPatient,
        record: selectedRecord,
        images: images,
        selectedImageIndex: 0,
      ),
    );
  }

  /// 进入批量分析页面
  void enterBatchAnalysis() {
    PageManager.ins.openNewTab(
      LabRouteNames.BatchAnalysis,
      "批量分析",
      args: LabBatchAnalysisInitArguments(
        patient: selectedPatient,
        record: selectedRecord,
        images: imageList,
        projectCode: selectedDataSourceId,
      ),
    );
  }

  /// 初始化数据源列表
  void initDataSourceList() async {
    List<ResearchProjectBaseDTO>? researchProjectList =
        await projectService.getResearchProjectListAsync(
      keyWord: "",
      searchType: ResearchProjectSearchTypeEnum.Undefined,
    );
    List<ProjectModel> projects = [];
    researchProjectList?.forEach((element) {
      projects.add(ProjectModel(
        id: element.code ?? '',
        name: element.name ?? '',
        type: ProjectType.created,
        projectIntroduction: element.introduction ?? '',
        organizationPatientType: element.patientType,
      ));
    });

    dataSourceList = projects;
    selectedDataSourceId = dataSourceList[0].id;
    await updatePatientList(selectedDataSourceId);
    update([dataSourceSelectorId]);
  }

  /// 更新数据源列表
  void updateDataSourceList() async {
    List<ResearchProjectBaseDTO>? researchProjectList =
        await projectService.getResearchProjectListAsync(
      keyWord: "",
      searchType: ResearchProjectSearchTypeEnum.Undefined,
    );
    List<ProjectModel> projects = [];
    researchProjectList?.forEach((element) {
      projects.add(ProjectModel(
        id: element.code ?? '',
        name: element.name ?? '',
        type: ProjectType.created,
        projectIntroduction: element.introduction ?? '',
        organizationPatientType: element.patientType,
      ));
    });

    dataSourceList = projects;
    state.noData = dataSourceList.length == 0;
    if (!dataSourceList.map((e) => e.id).contains(selectedDataSourceId)) {
      if (dataSourceList.length > 0) {
        selectedDataSourceId = dataSourceList.first.id;
      } else {
        selectedDataSourceId = '';
      }
      await updatePatientList(selectedDataSourceId);
    }
    update([dataSourceSelectorId]);
  }

  // 选择数据源
  Future<void> selectDataSource(String? projectId) async {
    if (projectId == null) return;
    selectedDataSourceId = projectId;
    await updatePatientList(projectId);
    update([dataSourceSelectorId]);
  }

  /// 获取项目详情
  Future<void> getResearchProjectDetailAsync(String? projectId) async {
    if (projectId == null) return;
    ResearchProjectDTO? detail = await projectService.getResearchProjectDetail(
      projectCode: projectId,
    );
    patientType = detail?.patientType ?? OrganizationPatientTypeEnum.Person;
    await getResearchProjectData(projectId);
  }

  Future<void> getResearchProjectData(
    String projectId,
  ) async {
    PageCollection<ResearchProjectDataDTO>? result =
        await projectService.getResearchProjectDataPagesAsync(
      projectCode: projectId,
      keyWord: dataSourceSearchInputController.text,
      pageIndex: 1,
      pageSize: 1000,
      sort: 0,
    );
    List<PatientModel> patients = [];
    result?.pageData?.forEach((element) {
      String patientName =
          FEncryptHelper.decryptBase64(element.patientName ?? '');
      if (patientName.isEmpty) {
        patientName = "未命名";
      }
      patients.add(PatientModel(
        id: element.devicePatientId ?? '',
        code: element.patientCode ?? '',
        name: patientName,
        isExistUrmData: element.isUrm,
        fileSize: CommonUtil.convertBytesToMegabytesOrGigabytes(
          int.parse(
            element.fileSize ?? '0',
          ),
        ),
      ));
    });
    if (result?.pageData?.isEmpty ?? true) {
      patientClassifyData = [];
      isPatientListLoading = false;
      state.noPatient = true;
      update([patientListId]);
      return;
    } else {
      patientClassifyData = [
        ClassifyData(
          classifyName: patientType == OrganizationPatientTypeEnum.Person
              ? "实验样本"
              : "实验样本",
          data: patients,
          showActionButton: true,
          showItemActionButton: true,
        ),
      ];
      state.noPatient = false;
    }

    if (patients.length > 0) {
      if (patientCodeByArguments != "") {
        updateRecordList(patientCodeByArguments);
      } else {
        updateRecordList(selectedPatient.code);
      }
    }

    isPatientListLoading = false;
    update([patientListId]);
  }

  // 根据数据源更新样本列表（病人列表）
  Future<void> updatePatientList(String projectId) async {
    isPatientListLoading = true;
    isRecordListLoading = true;
    isImageListLoading = true;
    update([patientListId, recordListId, imageListId]);
    if (projectId.isEmpty) {
      return;
    }
    await getResearchProjectDetailAsync(projectId);

    isPatientListLoading = false;
    update([patientListId, imageListId]);
  }

  // 根据病人 code 更新检查记录列表
  void updateRecordList(String patientCode) async {
    isRecordListLoading = true;
    isImageListLoading = true;
    update([recordListId, imageListId]);
    List<RecordModel> result = await projectService.getRecordDetail(
      patientCode: patientCode,
      patientType: patientType,
      selectedPatient: selectedPatient,
    );
    recordList = result;

    if (result.isEmpty) {
      state.noRecord = true;
      return;
    } else {
      state.selectedRecordIndex = 0;
      updateImageList(result.first.images);
      state.noRecord = false;
    }

    isRecordListLoading = false;
    update([recordListId]);
  }

  /// 切换测量公式
  void changeMeasureCalcuators() {
    List<DataItemDTO> patientInfo = selectedRecord.patientInfo;
    if (patientInfo.isNotEmpty) {
      DataItemDTO? dataItem = patientInfo.firstWhereOrNull((element) =>
          element.key == "Species" &&
          (element.value == "Mouse" || element.value == "Rat"));
      if (dataItem != null) {
        GlobalPatientConfig.switchSpecies(SpeciesType.mouse);
      } else {
        GlobalPatientConfig.switchSpecies(SpeciesType.animals);
      }
    }
  }

  // 根据检查记录 Id 更新图片列表
  void updateImageList(List<ImageModel> resultImage) {
    changeMeasureCalcuators();
    isImageListLoading = true;
    update([imageListId]);
    imageList = resultImage;
    isImageListLoading = false;
    update([imageListId]);
  }

  // 更新当前选中的检查下的图像列表
  void updateImageListByCurrRecord() async {
    // 判断当前是否选中了检查记录，如果有则获取检查下的图像列表
    if (recordList.isNotEmpty) {
      // 取当前选中的检查code，获取详情数据
      List<RecordModel> result = await projectService.getRecordDetail(
        patientCode: selectedPatient.code,
        patientType: patientType,
        selectedPatient: selectedPatient,
      );
      recordList = result;
      if (result.isEmpty) {
        state.noRecord = true;
        return;
      } else {
        if (result.length > state.selectedRecordIndex) {
          updateImageList(result[state.selectedRecordIndex].images);
        }
        state.noRecord = false;
      }
    }
  }

  void updateByLabDataActiveArguments(LabDataActiveArguments arguments) async {
    if (selectedDataSourceId != arguments.projectCode) {
      // selectedClassifyIndex = 0;
      selectedPatientIndex = 0;
    }
    patientCodeByArguments = arguments.patientCode;
    await selectDataSource(arguments.projectCode);
    selectPatientByCode(arguments.patientCode);

    /// 重置
    patientCodeByArguments = "";
  }

  @override
  void onSleep() {
    // cancelTimer();
    print("Lab Data onSleep: $tabHashCode");
  }

  @override
  void onActive(arguments) {
    updateDataSourceList();
    print("Lab Data onActive: $tabHashCode arguments: $arguments");
    if (arguments is LabDataActiveArguments) {
      updateByLabDataActiveArguments(arguments);
    } else {
      try {
        updateImageListByCurrRecord();
      } catch (e) {
        print(e);
      }
    }
  }

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
    initDataSourceList();

    /// 初始化语言包
    languageService.init();
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    super.onClose();
  }

  /// dispose 释放内存
  @override
  void dispose() {
    super.dispose();
  }

  void debugForHomePage() {
    Get.offNamed(RouteNames.Lab.Login);
  }
}

class LabDataActiveArguments {
  LabDataActiveArguments({
    required this.projectCode,
    required this.patientCode,
  });
  final String projectCode;
  final String patientCode;
}
