import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:making_school_asignment_app/common/job/homework_details.dart';
import 'package:making_school_asignment_app/page/home_page/children/quick_data_check/quick_data_check_state.dart';

import '../config/request_config.dart';

class Utils {
  static Utils? _instance;

  Utils._internal();

  static Utils getInstance() {
    _instance ??= Utils._internal();

    return _instance!;
  }

  /// 关闭键盘
  static void hideKeyboard() {
    final currentFocus = Get.focusScope?.nearestScope;
    if (currentFocus != null && !currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
      FocusManager.instance.primaryFocus?.unfocus();
    }
  }

  void setTimeOut(int seconds, VoidCallback call) => Future.delayed(Duration(seconds: seconds), call);

  // 是否是平板
  static bool isPad([double mobilePhoneScale = 1.2]) {
    return ScreenUtil().scaleWidth > mobilePhoneScale;
  }

  static String getDoubleRemoveZero(double? val, [String? defaultVal]) {
    try {
      if (val == null) throw Exception('数据为空');
      List<String> valArr = val.toString().split('.');
      if (valArr.length >= 2) {
        if (int.parse(valArr[1]) == 0) {
          return val.toInt().toString();
        }
        return val.toString();
      }
      return val.toInt().toString();
    } catch (e) {
      return defaultVal ?? '';
    }
  }

  /// 去除小数点
  static String doubleToStringAsFixed(double val, {int fractionDigits = 2}) {
    return val.toStringAsFixed(fractionDigits).replaceAll(RegExp(r'\.0*$'), '');
  }

  static calcRate(int divisor, int dividend) {
    if (dividend != 0) {
      return ((100 * divisor) / dividend);
      // return ((100 * divisor) / dividend).toStringAsFixed(0);
    } else {
      return 0.0;
    }
  }

  /// 秒转时分秒
  static String second2HMS(int sec, {bool isEasy = false}) {
    String hms = "0";
    if (!isEasy) hms = "0秒";
    if (sec > 0) {
      int h = sec ~/ 3600;
      int m = (sec % 3600) ~/ 60;
      int s = sec % 60;
      if (h > 0) {
        hms = "$h时$m分$s秒";
      } else {
        if (m > 0) {
          hms = "$m分$s秒";
        } else {
          hms = "$s秒";
        }
      }
    }
    return hms;
  }

  static getHomeworkData(HomeworkDetails data) {
    CountData dataCount = CountData();
    List<Dtls> kgt = data.dtls.where((w) => w.questionType == 1).toList();
    dataCount.kgtAnswerCount = kgt.where((w) => w.state != 0).length;
    dataCount.kgtOkCount = kgt.where((w) => w.state == 3).length;
    dataCount.kgtDtlCount = kgt.length;
    dataCount.kgtAnswerRate = Utils.calcRate(dataCount.kgtAnswerCount!, dataCount.kgtDtlCount!);
    dataCount.kgtOkRate = Utils.calcRate(dataCount.kgtOkCount!, dataCount.kgtDtlCount!);

    dataCount.kgtCorrectRate = Utils.calcRate(dataCount.kgtOkCount!, dataCount.kgtAnswerCount!);
    dataCount.kgtCount = data.questions.where((w) => w.questionType == 1).length;

    List<Dtls> zgt = data.dtls.where((w) => w.questionType == 2).toList();
    dataCount.zgtAnswerCount = zgt.where((w) => w.state != 0).length;
    dataCount.zgtOkCount = zgt.where((w) => w.state == 3).length;
    dataCount.zgtDtlCount = zgt.length;
    dataCount.zgtAnswerRate = Utils.calcRate(dataCount.zgtAnswerCount!, dataCount.zgtDtlCount!);
    dataCount.zgtOkRate = Utils.calcRate(dataCount.zgtOkCount!, dataCount.zgtDtlCount!);

    dataCount.zgtCorrectRate = Utils.calcRate(dataCount.zgtOkCount!, dataCount.zgtAnswerCount!);
    dataCount.zgtCount = data.questions.where((w) => w.questionType == 2).length;
    dataCount.studentCount = data.students.length;
    dataCount.priorityStudents = data.students.where((w) => w.priorityAnnotate!).toList();

//已提交学生数
    dataCount.studentSubmitCount = data.students.where((s) => s.state != 0).length;
    dataCount.studentSubmitStudents = data.students.where((s) => s.state != 0).toList();
//未提交学生数
    dataCount.noAnswerCount = data.students.length - dataCount.studentSubmitCount!;
    dataCount.noAnswerStudents = data.students.where((s) => s.state == 0).toList();

    for (var stu in data.students) {
      stu.kgtStu = kgt.where((w) => w.studentId == stu.studentId).toList();
      // stu.kgtStu!.sort((a, b) => num.parse(a.questionNo).compareTo(num.parse(b.questionNo)));
      // stu.kgtStu!.sort((a, b) => num.parse(a.questionNo).compareTo(num.parse(b.questionNo)));
      stu.kgtStu!.sort((a, b) {
        try {
          if (RegExp(r'^\d*\.?\d+$').hasMatch(a.questionNo) && RegExp(r'^\d*\.?\d+$').hasMatch(b.questionNo)) {
            return num.parse(a.questionNo).compareTo(num.parse(b.questionNo));
          } else {
            throw Exception();
          }
        } catch (e) {
          return a.questionNo.toLowerCase().compareTo(b.questionNo.toLowerCase());
        }
      });
      stu.kgtOkCount = stu.kgtStu!.where((w) => w.state == 3).length;
      stu.kgtErrorCount = stu.kgtStu!.where((w) => w.state == 2).length;
      stu.kgtAnswerCount = stu.kgtStu!.where((w) => w.state != 0).length;

      stu.zgtStu = zgt.where((w) => w.studentId == stu.studentId).toList();
      // stu.zgtStu!.sort((a, b) => num.parse(a.questionNo).compareTo(num.parse(b.questionNo)));
      stu.zgtStu!.sort((a, b) {
        try {
          if (RegExp(r'^\d*\.?\d+$').hasMatch(a.questionNo) && RegExp(r'^\d*\.?\d+$').hasMatch(b.questionNo)) {
            return num.parse(a.questionNo).compareTo(num.parse(b.questionNo));
          } else {
            throw Exception();
          }
        } catch (e) {
          return a.questionNo.toLowerCase().compareTo(b.questionNo.toLowerCase());
        }
      });
      //正确
      stu.zgtOkCount = stu.zgtStu!.where((w) => w.state == 3).length;
      //错误
      stu.zgtErrorCount = stu.zgtStu!.where((w) => w.state == 2).length;
      //待批阅
      stu.zgtUnrated = stu.zgtStu!.where((w) => w.state == 1).length;
      //未做
      stu.zgtAnswerCount = stu.zgtStu!.where((w) => w.state != 0).length;
      stu.isAllCorrect = stu.kgtOkCount! + stu.zgtOkCount! == kgt.length + zgt.length ? true : false;
      stu.allOk = data.dtls.where((w) {
        if (stu.studentId == w.studentId) {
          stu.useTime = w.useTime;
        }
        for (var que in data.questions) {
          if (w.templateId == que.templateId && w.questionNo == que.questionNo) {
            w.answer = que.answer;
            w.questionPicture = que.questionPicture;
          }
        }
        return w.studentId == stu.studentId && w.state != 3;
      }).length;
      if ((stu.kgtStu!.length - stu.kgtAnswerCount!) + (stu.zgtStu!.length - stu.zgtAnswerCount!) ==
          (stu.kgtStu!.length + stu.zgtStu!.length)) {
        stu.allNotDone = true;
      } else {
        stu.allNotDone = false;
      }
      stu.noAnswerCount = data.dtls.where((w) => w.state == 0 && stu.studentId == w.studentId).length;

      List<Questions> ques = data.questions;
      stu.queDtls = data.dtls
          .where((w) =>
              w.studentId == stu.studentId &&
              ques.indexWhere((q) => w.templateId == q.templateId && w.questionNo == q.questionNo) > -1)
          .toList();
      int okCount = stu.queDtls!.where((w) => w.state == 3).length;
      int ttlCount = stu.queDtls!.length;
      stu.okRate = Utils.calcRate(okCount, ttlCount);

      //完成率
      int answerCount = stu.queDtls!.where((w) => w.state != 0).length;
      stu.answerRate = Utils.calcRate(answerCount, ttlCount);

      var stuDtls = data.dtls.where((w) => w.studentId == stu.studentId);
      var secList = [];
      for (var sec in stuDtls) {
        if (sec.useTime >= 1) {
          var date = DateTime.parse(sec.lastAnswerTime!);
          var lastSec = (date.difference(DateTime(1970)).inSeconds).floor();

          secList.add(lastSec);
          secList.add(lastSec - sec.useTime);
        }
      }
      secList.sort();
      /* var maxSec = secList.isNotEmpty ? secList.last : 0;
      var minSec = secList.isNotEmpty ? secList.first : 0;*/
      final secTime = secList.isNotEmpty ? secList.last - secList.first : 0;
      stu.allTime = secTime;
      stu.ttlSec = second2HMS(secTime);
    }

    data.students.sort((a, b) {
      int num1 = a.state;
      int num2 = b.state;
      return num2.compareTo(num1);
    });
    // 按成绩等级分类学生
    final allCorrectStudents = data.students.where((w) => w.isAllCorrect == true).toList();
    dataCount.allCorrect = allCorrectStudents.length;
    dataCount.allCorrectStudents = allCorrectStudents;

    final levelOneStudents = data.students.where((s) => s.okRate! >= 85).toList();
    dataCount.levelOneCount = levelOneStudents.length;
    dataCount.levelOneStudents = levelOneStudents;

    final levelTwoStudents = data.students.where((s) => s.okRate! < 85 && s.okRate! >= 55).toList();
    dataCount.levelTwoCount = levelTwoStudents.length;
    dataCount.levelTwoStudents = levelTwoStudents;

    final levelThreeStudents = data.students.where((s) => s.okRate! < 55 && s.okRate! >= 25).toList();
    dataCount.levelThreeCount = levelThreeStudents.length;
    dataCount.levelThreeStudents = levelThreeStudents;

    final levelFourStudents = data.students.where((s) => s.okRate! < 25).toList();
    dataCount.levelFourCount = levelFourStudents.length;
    dataCount.levelFourStudents = levelFourStudents;

    for (var que in data.questions) {
      List<Dtls> ques =
          data.dtls.where((w) => w.templateId == que.templateId && w.questionNo == que.questionNo).toList();
      que.answerCount = ques.where((w) => w.state != 0).length;
      que.answerRate = Utils.calcRate(que.answerCount!, dataCount.studentCount!);
      int okCount = ques.where((w) => w.state == 3).length;
      que.okRate = Utils.calcRate(okCount, dataCount.studentCount!);
      que.priorityInfo = ques.where((w) {
        return dataCount.priorityStudents!.indexWhere((s) {
                  w.studentName = s.studentName;
                  return s.studentId == w.studentId;
                }) >
                -1 &&
            w.state != 3;
      }).toList();
      que.correctRate = Utils.calcRate(okCount, que.answerCount!);
      que.answerNgStudents = ques.where((w) {
        try {
          var student = data.students.firstWhere((s) => s.studentId == w.studentId);
          w.studentName = student.studentName;
        } catch (e) {
          w.studentName = '';
        }
        return w.state == 2;
      }).toList();

      que.noAnswerStudents = ques.where((w) {
        return w.state == 0;
      }).toList();
      que.answerOkStudents = ques.where((w) {
        return w.state == 3;
      }).toList();

      //作答效率
      int middleTime = 0;
      if (ques.length % 2 == 0) {
        int index = (ques.length / 2).ceil();
        middleTime = ((ques[index].useTime + ques[index - 1].useTime) / 2).ceil();
      } else {
        int index = ((ques.length + 1) / 2).ceil();
        middleTime = ques[index - 1].useTime;
      }

      var excellent = ques.where((w) => w.state == 3 && w.useTime <= middleTime).length;
      var good = ques.where((w) => w.state == 3 && w.useTime > middleTime).length;
      var middle = ques.where((w) => w.state != 3 && w.useTime <= middleTime).length;
      var differ = ques.where((w) => w.state != 3 && w.useTime > middleTime).length;

      que.overallTitles = [
        OverallTitles('优秀', excellent),
        OverallTitles('良好', good),
        OverallTitles('中', middle),
        OverallTitles('差', differ)
      ];

      Map<String, int> optInfos = {};
      for (var d in ques.where((w) => w.questionType == 1 && w.studentAnswer != null)) {
        final key = d.studentAnswer!;
        if (optInfos[key] != null) {
          optInfos[key] = optInfos[key]! + 1;
        } else {
          optInfos[key] = 1;
        }
      }
      List<SelectionRate> student = [];
      optInfos.forEach((key, value) {
        // optInfos[key] = Utils.calcRate(value, ques.length).round();
        List<Students> currentOptionStudents = data.students
            .where((s) => ques.where((w) => w.studentAnswer == key && w.studentId == s.studentId).isNotEmpty)
            .toList();
        //字母排序
        String upStr = key.toUpperCase();
        List<String> chars = upStr.split('')..sort();
        String sortedStr = chars.join();

        student.add(SelectionRate(sortedStr, Utils.calcRate(value, ques.length).round(), false, currentOptionStudents));
      });
      /* print('optitems=$optInfos');
      var ARate = Utils.calcRate(
          ques.where((w) => w.studentAnswer == "A").length, ques.length);*/
      que.options = student;
    }

    for (var know in data.knows) {
      List<Questions> ques =
          data.questions.where((w) => w.knows.indexWhere((k) => k.knowledgeId == know.knowledgeId) > -1).toList();
      List<Dtls> queDtls = data.dtls
          .where((w) => ques.indexWhere((q) => w.templateId == q.templateId && w.questionNo == q.questionNo) > -1)
          .toList();
      know.okCount = queDtls.where((w) => w.state == 3).length;
      know.ttlCount = queDtls.length;
      know.okRate = Utils.calcRate(know.okCount!, know.ttlCount!);
    }

    return dataCount;
  }

  static DateTime getWeekStartDate() {
    // DateTime now = DateTime.now();
    // int dayOfWeek = now.weekday; // 获取今天是周几（1代表周一，7代表周日）
    // int diff = dayOfWeek - 1; // 计算今天距离周一的天数差
    // if (diff < 0) {
    //   diff += 7; // 如果是周日，则需要加上一周的天数
    // }
    // return now.subtract(Duration(days: diff)); // 减去天数差，得到本周一的时间
    DateTime now = DateTime.now();
    return now.subtract(const Duration(days: 6));
  }

  static DateTime getWeekEndDate() {
    // DateTime now = DateTime.now();
    // int dayOfWeek = now.weekday; // 获取今天是周几
    // int diff = 7 - dayOfWeek; // 计算今天距离周日的天数差
    // if (diff == 0) {
    //   diff = 7; // 如果是周日，则加上一周的天数
    // }
    // return now.add(Duration(days: diff)); // 加上天数差减一，得到本周日的时间
    return DateTime.now();
  }
}

// 是否是平板
bool isPad([double mobilePhoneScale = 1.2]) {
  return ScreenUtil().scaleWidth > mobilePhoneScale;
}

void toUpState(Function(void Function()) setState, VoidCallback fn, bool mounted) {
  if (mounted) setState(fn);
}

void toPrint({required dynamic val, bool toPrintJson = false}) {
  bool printSwitch = RequestConfig.printSwitch;
  if (printSwitch && val != null) toPrintJson ? printJson(val) : print(val);
}

/// 单纯的Json格式输出打印
void printJson(Object object) {
  try {
    JsonEncoder encoder = const JsonEncoder.withIndent('  ');
    var encoderString = encoder.convert(object);
    // print(encoderString);
    // 不使用print()方法是因为这是单条输出，如果过长无法显示全
    // 所以使用debugPrint()
    debugPrint(encoderString);
    // 下面这语句的效果与debugPrint 相同
    //encoderString.split('\n').forEach((element) => print(element));
  } catch (e) {
    toPrint(val: e);
  }
}
