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

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/event_bus/jobs/job_do_papers_student_bus.dart';
import 'package:marking_app/common/model/event_bus/jobs/job_do_papers_submit_check_switch_bus.dart';
import 'package:marking_app/common/model/event_bus/jobs/job_do_synchro_tab.dart';
import 'package:marking_app/common/model/job/job_concerned_with_student.dart';
import 'package:marking_app/common/model/job/job_concerned_with_student_params.dart';
import 'package:marking_app/common/model/job/job_do_marking_status_info.dart';
import 'package:marking_app/common/model/job/job_page_tab.dart';
import 'package:marking_app/common/model/job/job_review_submission.dart';
import 'package:marking_app/common/model/job/marking_text_question_job.dart';
import 'package:marking_app/common/model/job/marking_text_question_job_tab_params.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/pages/homework_correction/components/new_version_of_homework/bottom_annotation_switch_job.dart';
import 'package:marking_app/pages/homework_correction/eventBus/marking_text_question_job_tab_params_bus.dart';
import 'package:marking_app/pages/homework_correction/providers/drawing_provider.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/index.dart';

// utils
import 'package:marking_app/utils/my_text.dart';
import 'package:marking_app/utils/request/rest_client.dart';

// HOOKS
import 'components/jobPictureOverview.dart';
import 'components/new_version_of_homework/favorite_widget.dart';
import 'eventBus/do_papers_job_refresh_bus.dart';
import 'eventBus/job_check_switching_question_tab_bus.dart';
import 'eventBus/job_notes_view_bus.dart';
import 'hooks/do_papers_job/use_do_paper_scoring.dart';
import 'hooks/do_papers_job/use_switch_student_and_type.dart';

// COMPONENTS
import 'components/new_version_of_homework/button_floating_action.dart';
import 'providers/do_job_obtain_grading_data_provider.dart';

part 'do_papers_job.g.dart';

// 作业批阅
class DoPapersJob extends HookWidget with EventBusMixin<DoPapersJobRefreshBus> {
  final int taskId; // 任务ID
  final int jobId;
  final String taskName;
  final String className; // 班级ID
  DoPapersJob({required this.taskId, required this.jobId, required this.taskName, required this.className, super.key});

  bool refresh = false;
  @override
  Widget build(BuildContext context) {
    useEffect(() {
      // SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
      WidgetsFlutterBinding.ensureInitialized();
      SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
      eventOn(callback: (DoPapersJobRefreshBus eventModel) {
        refresh = eventModel.flagRefresh;
      });
      return () {
        eventCancel();
      };
    }, []);
    return Scaffold(
      appBar: AppBar(
        // titleSpacing: 0,
        leading: IconButton(icon: Icon(Icons.arrow_back_ios), onPressed: () => Navigator.of(context).pop(refresh)),
        iconTheme: IconThemeData(color: Colors.black),
        title: quickText(taskName + '($className)'),
        backgroundColor: Colors.white,
        elevation: 0,
        actions: [
          FavoriteWidget(() => refresh = true),
          SizedBox(width: 5.w),
          ReturnToHomepage(),
        ],
      ),
      body: SafeArea(
        child: Column(
          children: [
            // 下拉切换
            $DropdownBoxSwitchStudentsOrTypeView(
              taskId: taskId,
              jobId: jobId,
              exitCallback: () => Navigator.of(context).pop(refresh),
            ),
            SizedBox(height: 1.h),
            Expanded(child: ExamPaperAndScoringView(taskId: taskId, className: className)),
            $BottomOperationBar()
          ],
        ),
      ),
      floatingActionButton: ButtonFloatingAction(),
      floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
    );
  }
}

/// 批阅情况（已阅55/54）
class ReviewStatusInfo extends HookWidget with CommonMixin {
  final int taskId;
  final int pageIndex;
  // final int schoolId;
  // final int gradeId;
  final String className;
  const ReviewStatusInfo({
    required this.taskId,
    required this.pageIndex,
    // required this.schoolId,
    // required this.gradeId,
    required this.className,
    super.key,
  });

  Future<JobDoMarkingStatusInfo?> getData() async {
    var _client = await getClient();
    var result = await _client.getJobPageIndexInfo(taskId, pageIndex);
    return result.data;
  }

  /// 获取未提交
  Future<List<JobConcernedWithStudent>?> getStudents() async {
    try {
      ToastUtils.showLoading();
      var _client = await getClient();
      var _result = await _client.getJobWithStudents(JobConcernedWithStudentParams([taskId], isCommit: false, pageIndex: pageIndex));
      if (_result.success) return _result.data;
    } catch (e) {
      ToastUtils.showError('获取数据失败，请重试');
    } finally {
      ToastUtils.dismiss();
    }
  }

  @override
  Widget build(BuildContext context) {
    var doMarkingInfo = useState<JobDoMarkingStatusInfo?>(null);
    useEffect(() {
      getData().then((value) => doMarkingInfo.value = value);
      return () {};
    }, []);

    if (doMarkingInfo.value == null) return Container();
    return InkWell(
      onTap: () async {
        List<JobConcernedWithStudent>? students = await getStudents();
        if (students == null) return;
        students = students..sort((e, e1) => e.studentName.compareTo(e1.studentName));
        showModalBottomSheet(
          context: context,
          elevation: 10,
          backgroundColor: Colors.white,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(10.r),
              topRight: Radius.circular(10.r),
            ),
          ),
          builder: (BuildContext context) {
            return Padding(
              padding: EdgeInsets.symmetric(horizontal: 2.w),
              child: Column(
                children: [
                  Container(
                    margin: EdgeInsets.only(top: 14.h),
                    child: quickText(
                      '当前页未提交学生名单',
                      size: 15.sp,
                      fontWeight: FontWeight.bold,
                      color: Color.fromRGBO(60, 60, 60, 1),
                    ),
                  ),
                  SizedBox(height: 10.h),
                  Expanded(
                    child: ListView(
                      padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
                      children: [
                        Wrap(
                          spacing: 6.0, // 主轴(水平)方向间距
                          runSpacing: 4.0, // 纵轴（垂直）方向间距
                          alignment: WrapAlignment.spaceAround, //沿主轴方向居中
                          children: students!.map((e) {
                            return Chip(
                              labelPadding: EdgeInsets.symmetric(vertical: 1.5.h, horizontal: 5.w),
                              backgroundColor: Color.fromRGBO(239, 242, 255, 1),
                              // avatar: CircleAvatar(
                              //   backgroundColor: Colors.white,
                              //   child: quickText(e.studentName.substring(0, 1),
                              //       size: 12.sp, color: Theme.of(context).primaryColor),
                              // ),
                              label: quickText(e.studentName, color: Color.fromRGBO(80, 94, 110, 1), size: 12.sp),
                            );
                          }).toList(),
                        ),
                      ],
                    ),
                  )
                ],
              ),
            );
          },
        );
      },
      child: Container(
        child: Row(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            quickText('已阅', color: Color.fromRGBO(117, 117, 117, 1), size: 10.sp),
            quickText(doMarkingInfo.value!.finishCount, color: Color.fromRGBO(76, 199, 147, 1), size: 12.sp, fontWeight: FontWeight.bold),
            quickText('/', color: Color.fromRGBO(117, 117, 117, 1), size: 12.sp),
            quickText(doMarkingInfo.value!.surplusNo, color: Color.fromRGBO(117, 117, 117, 1), size: 10.sp),
          ],
        ),
      ),
    );
  }
}

// 切换下拉框 （学生和试卷状态）
@hwidget
Widget $dropdownBoxSwitchStudentsOrTypeView(BuildContext context, {required Function() exitCallback, required int taskId, required int jobId}) {
  UseSwitchStudentAndType _useSwitchStudentAndType = UseSwitchStudentAndType.use(); // 学生和试卷状态

  // 当前tab改变时
  useValueChanged<List<JobPageTab>?, String>(_useSwitchStudentAndType.tabs.value, (_, __) {
    _useSwitchStudentAndType.eventFire(model: JobDoSynchroTab(_useSwitchStudentAndType.tabs.value));
  });

  // 当前tab改变时
  useValueChanged<JobPageTab?, String>(_useSwitchStudentAndType.currentTab.value, (_oldValue, __) {
    var thePageIndex = _useSwitchStudentAndType.currentTab.value?.pageIndex;
    JobDoPapersStudentBus? studentBus = _useSwitchStudentAndType.studentBusInfo.value;
    if (studentBus != null && studentBus.pageIndex == thePageIndex) return; // 获取试卷详情数据 定位到对应学生的数据 无需再通知详情获取数据
    if (thePageIndex != null) {
      _useSwitchStudentAndType.getDataForStudents(taskId: taskId, pageIndex: thePageIndex);
      _useSwitchStudentAndType.eventFire(model: MarkingTextQuestionJobTabParamsBus(taskId, thePageIndex));
    }
  });
  useValueChanged<JobConcernedWithStudent?, String>(_useSwitchStudentAndType.currentStudent.value, (oldData, __) {
    var studentId = _useSwitchStudentAndType.currentStudent.value?.studentId;
    JobDoPapersStudentBus? studentBus = _useSwitchStudentAndType.studentBusInfo.value;
    if (studentBus != null && studentBus.studentId == studentId) return; // 获取试卷详情数据 定位到对应学生的数据 无需再通知详情获取数据

    var thePageIndex = _useSwitchStudentAndType.currentTab.value?.pageIndex;
    if (thePageIndex != null) {
      _useSwitchStudentAndType.eventFire(model: MarkingTextQuestionJobTabParamsBus(taskId, thePageIndex, studentId: studentId));
    }
  });

  useEffect(() {
    _useSwitchStudentAndType.getData(taskId: taskId);
    _useSwitchStudentAndType.eventOn(
      callback: (val) {
        switch (val.runtimeType) {
          case JobDoPapersStudentBus:
            var studentInfo = val as JobDoPapersStudentBus;
            _useSwitchStudentAndType.studentBusInfo.value = studentInfo; // 赋值历史记录
            var selectedStudent =
                _useSwitchStudentAndType.studentData.value.firstWhereOrNull((element) => element.studentId == studentInfo.studentId);
            if (selectedStudent == null) {
              // 当前学生集合中没有此学生
              selectedStudent = JobConcernedWithStudent.fromJson(studentInfo.toJson());
              _useSwitchStudentAndType.studentData.value = [..._useSwitchStudentAndType.studentData.value, selectedStudent];
              _useSwitchStudentAndType.getDataForStudents(taskId: taskId);
            }
            _useSwitchStudentAndType.currentStudent.value = selectedStudent;
            _useSwitchStudentAndType.isFinish.value = studentInfo.isFinish;
            _useSwitchStudentAndType.isFirst.value = studentInfo.isFirst;
            _useSwitchStudentAndType.currentTab.value = _useSwitchStudentAndType.tabs.value.firstWhere((e) => e.pageIndex == studentInfo.pageIndex);
            break;
          case JobCheckSwitchingQuestionTabBus:
            // 检查切换试题体型
            _useSwitchStudentAndType.refreshQuestionTypeData(context, taskId: taskId, exitCallback: exitCallback);
            break;
          case MarkingTextQuestionJobTabParams: // 切换试题通知
            var moldeParams = val as MarkingTextQuestionJobTabParams;
            _useSwitchStudentAndType.currentTab.value =
                _useSwitchStudentAndType.tabs.value.firstWhere((element) => moldeParams.pageIndex == element.pageIndex);
            break;
          case JobDoPapersSubmitCheckSwitchBus: // 提交后切换试题通知
            var _currentTab = _useSwitchStudentAndType.currentTab.value;
            var _pageIndex = _currentTab?.pageIndex;
            if (_currentTab == null || _pageIndex == null) return;
            var params = MarkingTextQuestionJobTabParamsBus(taskId, _pageIndex);
            if (_currentTab.finishCount + 1 == _currentTab.total) {
              var _currentTabNew =
                  _useSwitchStudentAndType.tabs.value.firstWhereOrNull((e) => e.pageIndex != _currentTab.pageIndex && e.finishCount != e.total);
              // 如果全部都已经批阅完成就不需要跳转到不必要得批阅试题
              if (_currentTabNew != null) params.pageIndex = _currentTabNew.pageIndex;
            }
            var _theCurrentPage = _useSwitchStudentAndType.tabs.value.firstWhereOrNull((element) => element.pageIndex == _pageIndex);
            if (_theCurrentPage != null) {
              _theCurrentPage.finishCount += 1;
              _useSwitchStudentAndType.tabs.value = _useSwitchStudentAndType.tabs.value.map((e) => JobPageTab.fromJson(e.toJson())).toList();
            }
            _useSwitchStudentAndType.eventFire(model: params);
            break;
          default:
        }
      },
    );
    return () {
      _useSwitchStudentAndType.eventCancel();
    };
  }, []);
  return Container(
    padding: EdgeInsets.only(bottom: 2.r, left: 12.r, right: 12.r),
    decoration: BoxDecoration(
      color: Colors.white,
      boxShadow: [
        BoxShadow(
          color: const Color.fromRGBO(46, 91, 255, 0.2),
          offset: Offset(2.w, 2.h), //阴影y轴偏移量
          blurRadius: 14, //阴影模糊程度
          spreadRadius: 0.5, //阴影扩散程度
        )
      ],
    ),
    child: Row(
      children: [
        Expanded(
          flex: 3,
          child: Container(
            padding: EdgeInsets.only(left: 10.w),
            decoration: BoxDecoration(
              color: Color.fromRGBO(244, 244, 244, 1),
              borderRadius: BorderRadius.circular(4.r),
            ),
            child: DropdownButton(
              isExpanded: true,
              underline: Container(),
              padding: EdgeInsets.only(right: 4.w),
              icon: Icon(Icons.keyboard_arrow_down_rounded),
              value: _useSwitchStudentAndType.currentTab.value?.pageIndex,
              hint: Text('请选择作业页码'), // 锚点的显示文本
              onTap: () {
                print('点击选择作业页码.............');
                // 打开的时候请求刷新学生
              },
              items: _useSwitchStudentAndType.tabs.value.map((e) {
                return DropdownMenuItem(
                  child: quickText('${e.pageIndex}页', color: Color.fromRGBO(79, 79, 79, 1), size: 14.sp),
                  value: e.pageIndex,
                );
              }).toList(),
              onChanged: (value) {
                _useSwitchStudentAndType.currentTab.value = _useSwitchStudentAndType.tabs.value.firstWhere((element) => element.pageIndex == value);
              },
            ),
          ),
        ),
        Expanded(flex: 1, child: SizedBox()),
        Expanded(
          flex: 4,
          child: Container(
            padding: EdgeInsets.only(left: 10.w),
            decoration: BoxDecoration(
              color: Color.fromRGBO(244, 244, 244, 1),
              borderRadius: BorderRadius.circular(4.r),
            ),
            child: DropdownButton(
              onTap: () {
                // 打开的时候请求刷新学生
                _useSwitchStudentAndType.getDataForStudents(taskId: taskId);
              },
              padding: EdgeInsets.only(right: 4.w),
              icon: Icon(Icons.keyboard_arrow_down_rounded),
              value: _useSwitchStudentAndType.currentStudent.value?.studentId,
              underline: Container(),
              isExpanded: true,
              items: _useSwitchStudentAndType.studentData.value.map((e) {
                return DropdownMenuItem(
                  child: quickText(e.studentName, color: Color.fromRGBO(79, 79, 79, 1), size: 14.sp),
                  value: e.studentId,
                );
              }).toList(),
              hint: Text('请选择学生'), // 锚点的显示文本
              onChanged: (value) {
                JobConcernedWithStudent? currentStudent = _useSwitchStudentAndType.currentStudent.value;
                if (currentStudent?.studentId == value) return;
                _useSwitchStudentAndType.studentBusInfo.value = null; // 置空BUS通知记录
                _useSwitchStudentAndType.currentStudent.value =
                    _useSwitchStudentAndType.studentData.value.firstWhereOrNull((element) => element.studentId == value);
              },
            ),
          ),
        ),
        Expanded(flex: 1, child: SizedBox()),
        Expanded(
          flex: 4,
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              if (_useSwitchStudentAndType.isFinish.value &&
                  _useSwitchStudentAndType.tabs.value.firstWhereOrNull((e) => e.finishCount < e.total) != null)
                Expanded(
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Icon(Icons.flip_camera_android_outlined, size: 10.sp, color: Theme.of(context).primaryColor.withOpacity(0.8)),
                      SizedBox(width: 1.w),
                      InkWell(
                        onTap: () => easyThrottle(
                          'DO_PAPERS_JOB_CONTINUE_TO_REVIEW',
                          () {
                            var _currentTabNew = _useSwitchStudentAndType.tabs.value.firstWhere((e) => e.finishCount < e.total);
                            _useSwitchStudentAndType.eventFire(
                              model: MarkingTextQuestionJobTabParamsBus(taskId, _currentTabNew.pageIndex),
                            );
                          },
                        ),
                        child: quickText(
                          '继续批阅',
                          size: 10.sp,
                          decoration: TextDecoration.underline,
                          color: Theme.of(context).primaryColor.withOpacity(0.9),
                        ),
                      ),
                      SizedBox(width: 2.w),
                    ],
                  ),
                ),
              Expanded(
                child: InkWell(
                  onTap: () => easyThrottle('DO_PAPERS_JOB_HISTORICAL_HOMEWORK', () {
                    JobConcernedWithStudent? _studentModel = _useSwitchStudentAndType.currentStudent.value;
                    if (_studentModel == null) return;
                    String url =
                        '${RouterManager.jobPersonalDetailPath}?studentId=${_studentModel.studentId}&studentName=${Uri.encodeComponent(_studentModel.studentName)}';
                    RouterManager.router.navigateTo(context, url, transition: getTransition());
                  }),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Icon(Icons.location_history, size: 12.sp, color: Color.fromRGBO(104, 103, 103, 1)),
                      SizedBox(width: 1.w),
                      quickText(
                        '历史作业',
                        size: 10.sp,
                        decoration: TextDecoration.underline,
                        color: Theme.of(context).primaryColor.withOpacity(0.8),
                      ),
                    ],
                  ),
                ),
              ),
              Stack(
                alignment: const FractionalOffset(0.52, 0.24),
                children: [
                  Icon(
                    const IconData(0xe63d, fontFamily: "AlibabaIcon"),
                    size: 12.sp,
                    color: _useSwitchStudentAndType.isFirst.value ? Color.fromRGBO(76, 199, 147, 1) : Color.fromRGBO(164, 164, 164, 1),
                  ),
                  quickText('优先', size: 4.sp, color: Colors.white),
                ],
              ),
            ],
          ),
          // InkWell(
          //   onTap: () => easyThrottle(
          //       'prioritize_homework_review',
          //       () => !_useSwitchStudentAndType.isFirst.value
          //           ? _useSwitchStudentAndType.jobPriorityReviewJoin(jobId)
          //           : _useSwitchStudentAndType.jobPriorityReviewCancel(jobId)),
          //   child:
          //   Row(
          //     crossAxisAlignment: CrossAxisAlignment.center,
          //     mainAxisAlignment: MainAxisAlignment.start,
          //     children: [
          //       Stack(
          //         alignment: const FractionalOffset(0.52, 0.24),
          //         children: [
          //           Icon(
          //             const IconData(0xe63d, fontFamily: "AlibabaIcon"),
          //             size: 12.sp,
          //             color: _useSwitchStudentAndType.isFirst.value
          //                 ? Color.fromRGBO(76, 199, 147, 1)
          //                 : Color.fromRGBO(164, 164, 164, 1),
          //           ),
          //           quickText('优先', size: 4.sp, color: Colors.white),
          //         ],
          //       ),
          //       SizedBox(width: 1.2.w),
          //       quickText(
          //         '优先批阅',
          //         size: 10.sp,
          //         color: _useSwitchStudentAndType.isFirst.value
          //             ? Color.fromRGBO(76, 199, 147, 1)
          //             : Color.fromRGBO(164, 164, 164, 1),
          //       ),
          //     ],
          //   ),
          // ),
        ),
      ],
    ),
  );
}

// 试卷和打分键盘栏
class ExamPaperAndScoringView extends StatefulHookConsumerWidget {
  final int taskId;
  final String className;
  const ExamPaperAndScoringView({required this.taskId, required this.className, super.key});

  @override
  _EexamPaperAndScoringViewState createState() => _EexamPaperAndScoringViewState();
}

class _EexamPaperAndScoringViewState extends ConsumerState<ExamPaperAndScoringView> with EventBusMixin, CommonMixin {
  final GlobalKey<JobPictureOverviewState> scaffoldKeyPictureOverview = GlobalKey<JobPictureOverviewState>();
  Future<MarkingTextQuestionJob?>? _future; // 考试试卷
  MarkingTextQuestionJob? theJobData;
  bool firstLoading = true;
  JobDoSynchroTab? synchroTabs;
  late RemoveListener _doJobObtainGradingDataProviderListener; // 批注关闭监听

  @override
  void initState() {
    _doJobObtainGradingDataProviderListener = ref.read(doJobObtainGradingDataProvider.notifier).addListener((state) {
      if (state == null) return;
      _future = _getData(state);

      toUpState(setState, () {}, mounted);
    }, fireImmediately: false);
    eventOn(callback: (eventVal) {
      switch (eventVal.runtimeType) {
        case MarkingTextQuestionJobTabParamsBus:
          var theEventVal = eventVal as MarkingTextQuestionJobTabParamsBus;
          bool? isDefaultFirst;
          if (theJobData != null) {
            isDefaultFirst = theJobData!.pageIndex < theEventVal.pageIndex;
          }
          ref.read(doJobObtainGradingDataProvider.notifier).setVal(MarkingTextQuestionJobTabParams(
                pageIndex: theEventVal.pageIndex,
                taskId: theEventVal.taskId,
                studentId: theEventVal.studentId,
                previousPageIndex: theEventVal.previousPageIndex,
                nextPageIndex: theEventVal.nextPageIndex,
                isDefaultFirst: isDefaultFirst,
              ));
          break;
        case JobDoSynchroTab:
          synchroTabs = eventVal as JobDoSynchroTab;
          break;
        default:
      }
    });

    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
    try {
      _doJobObtainGradingDataProviderListener();
    } catch (e) {}
    eventCancel();
  }

  Future<MarkingTextQuestionJob?> _getData(MarkingTextQuestionJobTabParams params) async {
    try {
      RestClient _client = await getClient();
      BaseStructureResult<MarkingTextQuestionJob> _result = await _client.getJobTabOfExam(params);
      if (_result.success) {
        var jobDetails = _result.data;
        theJobData = jobDetails;
        if (jobDetails != null) {
          jobDetails.previousPageIndex = synchroTabs?.getPreviousPageIndex(jobDetails.pageIndex - 1);
          jobDetails.nextPageIndex = synchroTabs?.getNextPageIndex(jobDetails.pageIndex - 1);
          // 触发学生下拉选中
          try {
            // 清空已有数据
            ref.read(jobHomeWorkProvider.notifier).setVal([]);
          } catch (e) {}

          eventFire(model: JobQuestionsSwitch(jobDetails.taskId, jobDetails.studentId, jobDetails.paperId));
          eventFire(
            model: JobDoPapersStudentBus(
              jobDetails.studentId,
              jobDetails.studentName,
              jobDetails.pageIndex,
              jobDetails.isFirst,
              jobDetails.isFinish,
            ),
          );
        }
        return jobDetails;
      }
    } catch (e) {
      print(e);
    }

    return null;
  }

  /// 跳转试题
  void switchTestQuestions({required MarkingTextQuestionJob jobData, bool toNextQuestion = true}) {
    if (toNextQuestion) {
      // 下一题
      var model = MarkingTextQuestionJobTabParams(
        // 默认当前题型下标和当前题型下下一题没有下一题paperId为0
        taskId: widget.taskId,
        paperId: jobData.nextId,
        pageIndex: jobData.pageIndex,
        nextPageIndex: jobData.nextPageIndex,
        previousPageIndex: jobData.previousPageIndex,
        isDefaultFirst: true,
      );
      if (model.paperId == 0 && jobData.nextPageIndex != null) {
        // 切换题型页面
        model.paperId = null;
        model.pageIndex = jobData.nextPageIndex!;
        return eventFire(model: model);
      }
      return ref.read(doJobObtainGradingDataProvider.notifier).setVal(model);
    }

    var model = MarkingTextQuestionJobTabParams(
      taskId: widget.taskId,
      pageIndex: jobData.pageIndex,
      paperId: jobData.prevId,
      nextPageIndex: jobData.nextPageIndex,
      previousPageIndex: jobData.previousPageIndex,
      isDefaultFirst: false,
    );
    if (model.paperId == 0 && jobData.previousPageIndex != null) {
      model.paperId = null;
      model.pageIndex = jobData.previousPageIndex!;
      return eventFire(model: model);
    }

    ref.read(doJobObtainGradingDataProvider.notifier).setVal(model);
  }

  @override
  Widget build(BuildContext context) {
    if (_future == null) return Center(child: MyFutureBuilder.getBldLoad(context));

    return MyFutureBuilder.buildFutureBuilderOfSingleInstance<MarkingTextQuestionJob>(context, _future!, (jobData) {
      List<Questions> questions = jobData?.questions ?? [];

      bool canNormalPrevious = jobData != null && (jobData.prevId != 0 || jobData.previousPageIndex != null); //是否可以正常点击切换上一题
      bool canNormalNext = jobData != null && (jobData.nextId != 0 || jobData.nextPageIndex != null); //是否可以正常点击切换下一题

      return Stack(
        children: [
          Container(
            child: Row(children: [
              Expanded(
                flex: 7,
                child: Stack(
                  alignment: const FractionalOffset(0.96, 0.98),
                  children: [
                    LayoutBuilder(
                      builder: (BuildContext context, BoxConstraints constraints) {
                        final double containerWidth = constraints.maxWidth; // 展示区域总宽度
                        final double containerHeight = constraints.maxHeight; // 展示区域总宽度

                        if (jobData == null) return Container(); // 没有试题展示缩略图
                        return Stack(
                          children: [
                            JobPictureOverview(
                              jobData: jobData,
                              key: scaffoldKeyPictureOverview,
                              containerWidth: containerWidth,
                              containerHeight: containerHeight,
                            ),
                            if (canNormalPrevious)
                              Positioned(
                                left: 3.w,
                                top: (containerHeight / 2) - 20.h,
                                child: FloatingActionButton(
                                  heroTag: '点击前往上一题',
                                  tooltip: '点击前往上一题',
                                  focusColor: Theme.of(context).primaryColor,
                                  backgroundColor: const Color.fromRGBO(24, 32, 32, 0.1),
                                  elevation: 6.r,
                                  onPressed: () =>
                                      easyThrottle('TestQuestionSwitch', () => switchTestQuestions(jobData: jobData, toNextQuestion: false)),
                                  child: Icon(Icons.arrow_back_ios, color: Colors.white, size: 22.sp),
                                ),
                              ),
                            // 下一题 按钮
                            if (canNormalNext)
                              Positioned(
                                right: 2.w,
                                top: (containerHeight / 2) - 20.h,
                                child: FloatingActionButton(
                                  heroTag: '点击前往下一题',
                                  tooltip: '点击前往下一题',
                                  elevation: 6.r,
                                  backgroundColor: const Color.fromRGBO(24, 32, 32, 0.1),
                                  onPressed: () => easyThrottle('TestQuestionSwitch', () => switchTestQuestions(jobData: jobData)),
                                  child: Icon(Icons.arrow_forward_ios, color: Colors.white, size: 22.sp),
                                ),
                              ),
                          ],
                        );
                      },
                    ),

                    /// 批阅进度详情
                    ReviewStatusInfo(
                      taskId: widget.taskId,
                      pageIndex: jobData!.pageIndex,
                      className: widget.className,
                      // gradeId: null,
                      // schoolId: null,
                    )
                  ],
                ),
              ),
              Expanded(
                flex: 2,
                child: Container(
                  padding: EdgeInsets.only(bottom: 14.h, top: 6.h),
                  decoration: BoxDecoration(
                    color: Color.fromRGBO(159, 159, 159, 0.97),
                    boxShadow: [
                      BoxShadow(
                        color: const Color.fromRGBO(46, 91, 255, 0.2),
                        offset: Offset(0, 8.w), //阴影y轴偏移量
                        blurRadius: 1, //阴影模糊程度
                        spreadRadius: 2, //阴影扩散程度
                      )
                    ],
                  ),
                  child: (jobData?.questions ?? []).isEmpty
                      ? null
                      : $ExamPaperAndScoringKeyboardView(
                          data: jobData,
                          questions: questions,
                          toNextQuestionCall: () => switchTestQuestions(jobData: jobData),
                          switchQuestionTypes: () => eventFire(model: JobCheckSwitchingQuestionTabBus(jobData.pageIndex)),
                          viewHomeworkNotes: (JobReviewQuestions subJobQuestion) {
                            var _theBusModel =
                                JobNotesViewBus(taskId: jobData.taskId, paperId: jobData.paperId, questionNo: subJobQuestion.questionNo);
                            eventFire(model: _theBusModel);
                          },
                          scaffoldKeyPictureOverview: scaffoldKeyPictureOverview,
                        ),
                ),
              ),
            ]),
          ),
          // TODO 试题详情 错误提示
          if (jobData == null)
            $examPaperAndScoringErrorPromptView(() {
              var params = ref.read(doJobObtainGradingDataProvider);
              if (params == null) return;
              setState(() => (_future = _getData(params)));
            })
        ],
      );
    });
  }
}

// 右侧键盘
@hwidget
Widget $examPaperAndScoringKeyboardView(
  BuildContext context, {
  required MarkingTextQuestionJob data,
  required List<Questions> questions,
  required void Function() toNextQuestionCall,
  required void Function() switchQuestionTypes,
  required void Function(JobReviewQuestions subJobQuestion) viewHomeworkNotes, // 查看笔记
  required GlobalKey<JobPictureOverviewState> scaffoldKeyPictureOverview,
}) {
  var _useDoScoring = UseDoPaperScoring.use(data: data);

  /// 提交
  Future<void> toSubmit() async {
    _useDoScoring.submitForReview(context, scaffoldKeyPictureOverview).then((value) {
      if (!value) return;

      _useDoScoring.eventFire(model: DoPapersJobRefreshBus(flagRefresh: true));
      var nextId = data.nextId;
      if (nextId == 0) {
        // 没有下一道题了 判断是否需要跳转其他体型页面
        switchQuestionTypes();
        return;
      }
      // 有下一道题 自动跳转下一道题
      // toNextQuestionCall();
      _useDoScoring.eventFire(model: JobDoPapersSubmitCheckSwitchBus());
    });
  }

  useEffect(() {
    _useDoScoring.eventOn(callback: (JobNotesViewBus busModel) {
      JobNotesViewBus? oldBusModel = _useDoScoring.useStateBusData.value;
      if (oldBusModel != null) {
        if (oldBusModel.questionNo == busModel.questionNo) {
          _useDoScoring.useStateBusData.value = null;
          return;
        }
      }
      _useDoScoring.useStateBusData.value = busModel;
    });
    return () {
      _useDoScoring.eventCancel();
    };
  }, []);

  return Column(
    children: [
      Expanded(
        child: ListView.builder(
          padding: EdgeInsets.zero,
          itemCount: questions.length,
          itemBuilder: (BuildContext context, int index) {
            Questions question = questions[index];

            JobReviewQuestions subJobQuestion = _useDoScoring.questionsMap.value[question.questionNo]!;

            JobNotesViewBus? currentNotesQuestion = _useDoScoring.useStateBusData.value;
            Color textColor = Colors.white;
            if (currentNotesQuestion?.questionNo == question.questionNo) textColor = Color.fromRGBO(255, 159, 15, 1);

            return ListTile(
              onTap: () {},
              contentPadding: EdgeInsets.zero,
              title: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  $MaterialBtn(
                    onTap: () => easyThrottle('view_homework_notes', () => viewHomeworkNotes(subJobQuestion)),
                    bgc: Color.fromRGBO(88, 87, 87, 1),
                    child: Container(
                      width: double.infinity,
                      alignment: Alignment.center,
                      padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
                      decoration: BoxDecoration(border: Border(bottom: BorderSide(width: 0.2.r, color: Colors.white))),
                      child: Row(
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: [
                          Expanded(
                            child: Row(
                              mainAxisSize: MainAxisSize.min,
                              crossAxisAlignment: CrossAxisAlignment.end,
                              children: [
                                quickText(question.questionNo, size: 16.sp, color: textColor, fontWeight: FontWeight.bold),
                                Padding(
                                  padding: EdgeInsets.only(bottom: 1.h),
                                  child: quickText('题', size: 11.sp, color: textColor),
                                ),
                              ],
                            ),
                          ),
                          if (question.accuracy > 0)
                            Padding(
                              padding: EdgeInsets.only(bottom: 1.5.h),
                              child: quickText(
                                '正确率：${getDoubleRemoveZero(question.accuracy, question.accuracy.toString())}%',
                                size: 8.sp,
                                color: Colors.white,
                                align: TextAlign.end,
                              ),
                            )
                        ],
                      ),
                    ),
                  ),
                  Container(
                    child: Row(
                      children: [
                        Expanded(
                          child: $MaterialBtn(
                            bgc: Color.fromRGBO(237, 237, 237, 1),
                            onTap: () {
                              _useDoScoring.goToScoringShortcut(
                                scoring: ScoringMethodEnum.CORRECT,
                                questionNo: question.questionNo,
                              );
                              var noAnswerQuestion = _useDoScoring.submittedData.value.questions.firstWhereOrNull((e) => e.score == null);
                              if (noAnswerQuestion == null) toSubmit();
                            },
                            child: Container(
                              padding: EdgeInsets.symmetric(vertical: 12.r),
                              alignment: Alignment.center,
                              child: quickText(
                                '对',
                                color: subJobQuestion.score == 2 ? Color.fromRGBO(255, 152, 0, 1) : Color.fromRGBO(114, 114, 114, 1),
                                fontWeight: FontWeight.bold,
                                size: 12.sp,
                              ),
                            ),
                          ),
                        ),
                        SizedBox(width: 0.2.w),
                        Expanded(
                          child: $MaterialBtn(
                            onTap: () {
                              _useDoScoring.goToScoringShortcut(
                                scoring: ScoringMethodEnum.CORRECT_HALF,
                                questionNo: question.questionNo,
                              );
                              var noAnswerQuestion = _useDoScoring.submittedData.value.questions.firstWhereOrNull((e) => e.score == null);
                              if (noAnswerQuestion == null) toSubmit();
                            },
                            bgc: Color.fromRGBO(237, 237, 237, 1),
                            child: Container(
                              padding: EdgeInsets.symmetric(vertical: 12.r),
                              alignment: Alignment.center,
                              child: quickText(
                                '半',
                                color: subJobQuestion.score == 1 ? Color.fromRGBO(255, 152, 0, 1) : Color.fromRGBO(114, 114, 114, 1),
                                fontWeight: FontWeight.bold,
                                size: 12.sp,
                              ),
                            ),
                          ),
                        ),
                        SizedBox(width: 0.2.w),
                        Expanded(
                          child: $MaterialBtn(
                            onTap: () {
                              _useDoScoring.goToScoringShortcut(
                                scoring: ScoringMethodEnum.WRONG,
                                questionNo: question.questionNo,
                              );
                              var noAnswerQuestion = _useDoScoring.submittedData.value.questions.firstWhereOrNull((e) => e.score == null);
                              if (noAnswerQuestion == null) toSubmit();
                            },
                            bgc: Color.fromRGBO(237, 237, 237, 1),
                            child: Container(
                              padding: EdgeInsets.symmetric(vertical: 12.r),
                              alignment: Alignment.center,
                              child: quickText(
                                '错',
                                color: subJobQuestion.score == 0 ? Color.fromRGBO(255, 152, 0, 1) : Color.fromRGBO(114, 114, 114, 1),
                                fontWeight: FontWeight.bold,
                                size: 12.sp,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  SizedBox(height: 16.h),
                ],
              ),
            );
          },
        ),
      ),
      SizedBox(height: 3.h),
      Container(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 10.r),
              child: $MaterialBtn(
                bgc: Colors.white,
                borderRadius: BorderRadius.circular(2.r),
                onTap: () => easyThrottle('homework_review_submission_callback', () {
                  _useDoScoring.goToScoringShortcut(enumMode: ToScoringShortcut.ALL_PAIRS);
                  toSubmit();
                }, duration: Duration(milliseconds: 500)),
                child: Container(
                  width: double.infinity,
                  alignment: Alignment.center,
                  padding: EdgeInsets.symmetric(vertical: 8.r),
                  decoration: BoxDecoration(borderRadius: BorderRadius.circular(2.r)),
                  child: quickText(
                    '全对',
                    size: 12.sp,
                    color: Color.fromRGBO(81, 81, 81, 1),
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            SizedBox(height: 7.h),
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 10.r),
              child: $MaterialBtn(
                bgc: Colors.white,
                borderRadius: BorderRadius.circular(2.r),
                onTap: () => easyThrottle('homework_review_submission_callback', () {
                  _useDoScoring.goToScoringShortcut(enumMode: ToScoringShortcut.ALL_WRONG);
                  toSubmit();
                }, duration: Duration(milliseconds: 500)),
                child: Container(
                  width: double.infinity,
                  alignment: Alignment.center,
                  padding: EdgeInsets.symmetric(vertical: 8.r),
                  decoration: BoxDecoration(borderRadius: BorderRadius.circular(2.r)),
                  child: quickText(
                    '全错',
                    size: 12.sp,
                    color: Color.fromRGBO(81, 81, 81, 1),
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            SizedBox(height: 7.h),
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 10.r),
              child: $MaterialBtn(
                bgc: Colors.transparent,
                borderRadius: BorderRadius.circular(2.r),
                onTap: () => _useDoScoring.goToScoringShortcut(enumMode: ToScoringShortcut.CANCELLATION),
                child: Container(
                  width: double.infinity,
                  alignment: Alignment.center,
                  padding: EdgeInsets.symmetric(vertical: 8.r),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(2.r),
                    border: Border.all(
                      width: 1.r,
                      color: Colors.white,
                    ),
                  ),
                  child: quickText(
                    '取消',
                    size: 12.sp,
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            SizedBox(height: 26.h),
          ],
        ),
      ),
      if (questions.isNotEmpty)
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 10.r),
          child: $MaterialBtn(
            bgc: Colors.white,
            splashColor: Theme.of(context).primaryColor.withOpacity(0.8),
            borderRadius: BorderRadius.circular(2.r),
            onTap: () => easyThrottle('homework_review_submission_main_callback', () => toSubmit(), duration: Duration(seconds: 1)),
            child: Container(
              width: double.infinity,
              alignment: Alignment.center,
              padding: EdgeInsets.symmetric(vertical: 10.r),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(2.r),
                border: Border.all(width: 1.r, color: Colors.white),
              ),
              child: quickText(
                '提交',
                size: 12.sp,
                color: Color.fromRGBO(55, 55, 55, 1),
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ),
    ],
  );
}

@swidget
Widget $materialBtn({required Widget child, Color? bgc, Color? splashColor, GestureTapCallback? onTap, BorderRadiusGeometry? borderRadius}) {
  return Material(
    color: bgc,
    borderRadius: borderRadius,
    child: InkWell(onTap: onTap, splashColor: splashColor, child: child),
  );
}

// 底部操作栏
@hwidget
Widget $bottomOperationBar() {
  return OrientationBuilder(
    builder: (BuildContext context, Orientation orientation) {
      return BottomAnnotationSwitchJob(maxWidth: double.infinity, homework: true);
    },
  );
}

// 试题详情 错误提示
@hwidget
Widget $examPaperAndScoringErrorPromptView(Function call) {
  return Container(
    alignment: Alignment.center,
    child: ElevatedButton(child: quickText('请求失败，点击重新请求', color: Colors.white), onPressed: () => call()),
  );
}
