import 'dart:convert';
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:crypto/crypto.dart';
import 'package:pointycastle/export.dart';
import '../models/login_status.dart';
import '../models/course.dart';
import 'http_client.dart';
import '../utils/retry_handler.dart';

/// AUFE教务系统连接类
class AUFEConnection {
  final String userId;
  final String ecPassword;
  final String password;

  late HTTPClient _client;
  String? _twfId;
  String? _token;
  bool _ecLogged = false;
  bool _uaapLogged = false;
  DateTime _lastCheck = DateTime.now();

  // 配置常量
  static const String serverUrl = 'https://vpn.aufe.edu.cn';
  static const String uaapLoginUrl =
      'http://uaap-aufe-edu-cn.vpn2.aufe.edu.cn:8118/cas/login?service=http%3A%2F%2Fjwcxk2.aufe.edu.cn%2Fj_spring_cas_security_check';
  static const String uaapCheckUrl =
      'http://jwcxk2-aufe-edu-cn.vpn2.aufe.edu.cn:8118/';
  static const String ecCheckUrl =
      'http://txzx-aufe-edu-cn-s.vpn2.aufe.edu.cn:8118/dzzy/list.htm';

  AUFEConnection({
    required this.userId,
    required this.ecPassword,
    required this.password,
  });

  /// 初始化HTTP客户端
  void startClient() {
    _client = HTTPClient(baseUrl: serverUrl, timeout: 30000);
  }

  /// EC系统登录（RSA加密）
  Future<ECLoginStatus> ecLogin() async {
    try {
      return await RetryHandler.retry(
        operation: () async => await _performEcLogin(),
        retryIf: RetryHandler.shouldRetryOnError,
        maxAttempts: 3,
      );
    } catch (e) {
      return ECLoginStatus(failUnknownError: true);
    }
  }

  Future<ECLoginStatus> _performEcLogin() async {
    try {
      // 1. 获取认证参数
      final response = await _client.get('/por/login_auth.csp?apiversion=1');
      final responseText = response.data.toString();

      // 2. 提取TwfID
      final twfIdMatch = RegExp(
        r'<TwfID>(.*?)</TwfID>',
      ).firstMatch(responseText);
      if (twfIdMatch == null) {
        return ECLoginStatus(failNotFoundTwfid: true);
      }
      _twfId = twfIdMatch.group(1);

      // 3. 提取RSA密钥
      final rsaKeyMatch = RegExp(
        r'<RSA_ENCRYPT_KEY>(.*?)</RSA_ENCRYPT_KEY>',
      ).firstMatch(responseText);
      if (rsaKeyMatch == null) {
        return ECLoginStatus(failNotFoundRsaKey: true);
      }
      final rsaKey = rsaKeyMatch.group(1)!;

      // 4. 提取RSA指数
      final rsaExpMatch = RegExp(
        r'<RSA_ENCRYPT_EXP>(.*?)</RSA_ENCRYPT_EXP>',
      ).firstMatch(responseText);
      if (rsaExpMatch == null) {
        return ECLoginStatus(failNotFoundRsaExp: true);
      }
      final rsaExp = rsaExpMatch.group(1)!;

      // 5. 提取CSRF代码
      final csrfMatch = RegExp(
        r'<CSRF_RAND_CODE>(.*?)</CSRF_RAND_CODE>',
      ).firstMatch(responseText);
      if (csrfMatch == null) {
        return ECLoginStatus(failNotFoundCsrfCode: true);
      }
      final csrfCode = csrfMatch.group(1)!;

      // 6. RSA加密密码
      final passwordToEncrypt = '${ecPassword}_$csrfCode';
      final encryptedPassword = _rsaEncrypt(passwordToEncrypt, rsaKey, rsaExp);

      // 7. 执行登录
      final loginResponse = await _client.post(
        '/por/login_psw.csp?anti_replay=1&encrypt=1&type=cs',
        data: {
          'svpn_rand_code': '',
          'mitm': '',
          'svpn_req_randcode': csrfCode,
          'svpn_name': userId,
          'svpn_password': encryptedPassword,
        },
        options: Options(
          contentType: Headers.formUrlEncodedContentType,
          headers: {'Cookie': 'TWFID=$_twfId'},
        ),
      );

      final loginResponseText = loginResponse.data.toString();

      // 8. 检查登录结果
      if (loginResponseText.contains('<Result>1</Result>')) {
        _client.setCookie('TWFID', _twfId!);
        _ecLogged = true;
        return ECLoginStatus(success: true);
      } else if (loginResponseText.contains('Invalid username or password!')) {
        return ECLoginStatus(failInvalidCredentials: true);
      } else if (loginResponseText.contains('[CDATA[maybe attacked]]') ||
          loginResponseText.contains('CAPTCHA required')) {
        return ECLoginStatus(failMaybeAttacked: true);
      } else {
        return ECLoginStatus(failUnknownError: true);
      }
    } on DioException catch (e) {
      return ECLoginStatus(failNetworkError: true);
    } catch (e) {
      return ECLoginStatus(failUnknownError: true);
    }
  }

  /// RSA加密
  String _rsaEncrypt(String plaintext, String modulusHex, String exponentStr) {
    // 解析模数和指数
    final modulus = BigInt.parse(modulusHex, radix: 16);
    final exponent = BigInt.parse(exponentStr);

    // 创建RSA公钥
    final publicKey = RSAPublicKey(modulus, exponent);

    // 创建加密器
    final encryptor = PKCS1Encoding(RSAEngine());
    encryptor.init(true, PublicKeyParameter<RSAPublicKey>(publicKey));

    // 加密
    final plainBytes = utf8.encode(plaintext);
    final encrypted = encryptor.process(Uint8List.fromList(plainBytes));

    // 转换为十六进制字符串
    return encrypted.map((b) => b.toRadixString(16).padLeft(2, '0')).join('');
  }

  /// UAAP系统登录（DES加密）
  Future<UAAPLoginStatus> uaapLogin() async {
    try {
      return await RetryHandler.retry(
        operation: () async => await _performUaapLogin(),
        retryIf: RetryHandler.shouldRetryOnError,
        maxAttempts: 3,
      );
    } catch (e) {
      return UAAPLoginStatus(failUnknownError: true);
    }
  }

  Future<UAAPLoginStatus> _performUaapLogin() async {
    try {
      // 1. 获取登录页面
      final response = await _client.get(uaapLoginUrl);
      final responseText = response.data.toString();

      // 2. 提取lt参数
      final ltMatch = RegExp(
        r'name="lt" value="(.*?)"',
      ).firstMatch(responseText);
      if (ltMatch == null) {
        return UAAPLoginStatus(failNotFoundLt: true);
      }
      final ltValue = ltMatch.group(1)!;

      // 3. 提取execution参数
      final executionMatch = RegExp(
        r'name="execution" value="(.*?)"',
      ).firstMatch(responseText);
      if (executionMatch == null) {
        return UAAPLoginStatus(failNotFoundExecution: true);
      }
      final executionValue = executionMatch.group(1)!;

      // 4. DES加密密码
      final encryptedPassword = _desEncrypt(password, ltValue);

      // 5. 提交登录表单
      final loginResponse = await _client.post(
        uaapLoginUrl,
        data: {
          'username': userId,
          'password': encryptedPassword,
          'lt': ltValue,
          'execution': executionValue,
          '_eventId': 'submit',
          'submit': 'LOGIN',
        },
        options: Options(
          contentType: Headers.formUrlEncodedContentType,
          followRedirects: false,
          validateStatus: (status) => status! < 500,
        ),
      );

      // 6. 检查登录结果并访问重定向URL以建立session
      if (loginResponse.statusCode == 302) {
        final location = loginResponse.headers['location']?.first ?? '';
        print('🔐 UAAP redirect location: $location');

        if (location.contains('ticket=')) {
          // 访问重定向URL以完成CAS认证并建立session
          print('🔐 Following redirect to establish session...');
          final ticketResponse = await _client.get(
            location,
            options: Options(
              followRedirects: true,
              validateStatus: (status) => status! < 500,
            ),
          );
          print('🔐 Ticket response status: ${ticketResponse.statusCode}');

          _uaapLogged = true;
          return UAAPLoginStatus(success: true);
        }
      }

      final loginResponseText = loginResponse.data.toString();
      if (loginResponseText.contains('Invalid username or password')) {
        return UAAPLoginStatus(failInvalidCredentials: true);
      }

      return UAAPLoginStatus(failUnknownError: true);
    } on DioException catch (e) {
      return UAAPLoginStatus(failNetworkError: true);
    } catch (e) {
      return UAAPLoginStatus(failUnknownError: true);
    }
  }

  /// DES加密（使用TripleDES ECB模式）
  String _desEncrypt(String plaintext, String key) {
    // 处理密钥 - 取前8字节
    var keyBytes = utf8.encode(key);
    if (keyBytes.length > 8) {
      keyBytes = keyBytes.sublist(0, 8);
    } else if (keyBytes.length < 8) {
      // 不足8字节用0填充
      keyBytes = Uint8List(8)..setRange(0, keyBytes.length, keyBytes);
    }

    // 创建DES密钥（TripleDES使用相同的8字节密钥重复3次）
    final desKey = KeyParameter(
      Uint8List(24)
        ..setRange(0, 8, keyBytes)
        ..setRange(8, 16, keyBytes)
        ..setRange(16, 24, keyBytes),
    );

    // 创建加密器
    final cipher = PaddedBlockCipherImpl(PKCS7Padding(), DESedeEngine());
    cipher.init(true, PaddedBlockCipherParameters(desKey, null));

    // 加密
    final plainBytes = utf8.encode(plaintext);
    final encrypted = cipher.process(Uint8List.fromList(plainBytes));

    // Base64编码
    return base64.encode(encrypted);
  }

  /// 检查EC登录状态
  Future<ECCheckStatus> checkEcLoginStatus() async {
    if (!_ecLogged) {
      return ECCheckStatus(loggedIn: false);
    }

    try {
      final response = await _client.get(ecCheckUrl);
      if (response.statusCode == 200) {
        return ECCheckStatus(loggedIn: true);
      } else {
        return ECCheckStatus(loggedIn: false);
      }
    } on DioException catch (e) {
      return ECCheckStatus(failNetworkError: true);
    } catch (e) {
      return ECCheckStatus(failUnknownError: true);
    }
  }

  /// 检查UAAP登录状态
  Future<ECCheckStatus> checkUaapLoginStatus() async {
    return ECCheckStatus(loggedIn: _uaapLogged);
  }

  /// 健康检查
  Future<bool> healthCheck() async {
    final delta = DateTime.now().difference(_lastCheck);

    // 5分钟未检查则视为不健康
    if (delta.inSeconds > 300) {
      return false;
    }

    // 检查UAAP登录状态
    final uaapStatus = await checkUaapLoginStatus();
    if (!uaapStatus.isLoggedIn) {
      return false;
    }

    // 检查EC登录状态
    final ecStatus = await checkEcLoginStatus();
    if (!ecStatus.isLoggedIn) {
      return false;
    }

    return true;
  }

  /// 更新健康检查时间戳
  void healthCheckpoint() {
    _lastCheck = DateTime.now();
  }

  /// 关闭连接
  Future<void> close() async {
    _client.close();
  }

  /// 获取HTTP客户端
  HTTPClient get client {
    healthCheckpoint();
    return _client;
  }

  /// 获取CSRF Token
  Future<String?> getToken() async {
    try {
      final response = await _client.get(
        'http://jwcxk2-aufe-edu-cn.vpn2.aufe.edu.cn:8118/student/teachingEvaluation/evaluation/index',
      );

      if (response.statusCode != 200) {
        return null;
      }

      final html = response.data.toString();
      final tokenMatch = RegExp(
        r'id="tokenValue"[^>]*value="([^"]*)"',
      ).firstMatch(html);

      if (tokenMatch != null) {
        _token = tokenMatch.group(1);
        return _token;
      }

      return null;
    } catch (e) {
      return null;
    }
  }

  /// 获取待评课程列表
  Future<List<Course>> fetchCourseList() async {
    try {
      final response = await _client.post(
        'http://jwcxk2-aufe-edu-cn.vpn2.aufe.edu.cn:8118/student/teachingEvaluation/teachingEvaluation/search?sf_request_type=ajax',
        data: {'optType': '1', 'pagesize': '50'},
        options: Options(contentType: Headers.formUrlEncodedContentType),
      );

      if (response.statusCode != 200) {
        return [];
      }

      final data = response.data;
      if (data is Map<String, dynamic> && data['data'] is List) {
        final courseList = (data['data'] as List)
            .map((item) => _parseCourse(item))
            .where((course) => course != null)
            .cast<Course>()
            .toList();
        return courseList;
      }

      return [];
    } catch (e) {
      return [];
    }
  }

  /// 解析课程数据
  Course? _parseCourse(dynamic item) {
    try {
      if (item is! Map<String, dynamic>) return null;

      final id = item['id'] as Map<String, dynamic>?;
      final questionnaire = item['questionnaire'] as Map<String, dynamic>?;

      return Course(
        id: id?['evaluatedPeople']?.toString() ?? '',
        name: item['evaluationContent']?.toString() ?? '',
        teacher: item['evaluatedPeople']?.toString() ?? '',
        evaluatedPeople: item['evaluatedPeople']?.toString() ?? '',
        evaluatedPeopleNumber: id?['evaluatedPeople']?.toString() ?? '',
        coureSequenceNumber: id?['coureSequenceNumber']?.toString() ?? '',
        evaluationContentNumber:
            id?['evaluationContentNumber']?.toString() ?? '',
        questionnaireCode:
            questionnaire?['questionnaireNumber']?.toString() ?? '',
        questionnaireName:
            questionnaire?['questionnaireName']?.toString() ?? '',
        isEvaluated: item['isEvaluated']?.toString() == '是',
      );
    } catch (e) {
      return null;
    }
  }

  /// 访问评价页面并返回HTML内容
  Future<String?> accessEvaluationPage(
    Course course, {
    int? totalCourses,
  }) async {
    try {
      print('📝 Accessing evaluation page for: ${course.name}');

      if (_token == null) {
        print('📝 Getting token first...');
        await getToken();
        print('📝 Token: $_token');
      }

      // count is the total number of courses in the course list
      final count = totalCourses?.toString() ?? '28';
      print('📝 Using count: $count (total courses: $totalCourses)');

      print('📝 Posting to evaluation page...');
      final response = await _client.post(
        'http://jwcxk2-aufe-edu-cn.vpn2.aufe.edu.cn:8118/student/teachingEvaluation/teachingEvaluation/evaluationPage',
        data: {
          'count': count,
          'evaluatedPeople': course.evaluatedPeople,
          'evaluatedPeopleNumber': course.evaluatedPeopleNumber,
          'questionnaireCode': course.questionnaireCode,
          'questionnaireName': course.questionnaireName,
          'coureSequenceNumber': course.coureSequenceNumber,
          'evaluationContentNumber': course.evaluationContentNumber,
          'evaluationContentContent': '',
          'tokenValue': _token ?? '',
        },
        options: Options(contentType: Headers.formUrlEncodedContentType),
      );

      print('📝 Access evaluation page status: ${response.statusCode}');

      if (response.statusCode == 200) {
        final html = response.data.toString();
        print('📝 Got HTML content, length: ${html.length}');
        return html;
      }

      return null;
    } catch (e, stackTrace) {
      print('❌ accessEvaluationPage error: $e');
      print('❌ Stack trace: $stackTrace');
      return null;
    }
  }

  /// 提交评价表单
  Future<EvaluationResponse> submitEvaluation(
    Map<String, String> formData,
  ) async {
    try {
      print('📤 Submitting evaluation with form data:');
      print('📤 Form data entries: ${formData.length}');
      formData.forEach((key, value) {
        print(
          '   $key = ${value.length > 50 ? value.substring(0, 50) + "..." : value}',
        );
      });

      final response = await _client.post(
        'http://jwcxk2-aufe-edu-cn.vpn2.aufe.edu.cn:8118/student/teachingEvaluation/teachingEvaluation/assessment?sf_request_type=ajax',
        data: formData,
        options: Options(contentType: Headers.formUrlEncodedContentType),
      );

      print('📤 Submit response status: ${response.statusCode}');
      print('📤 Submit response data: ${response.data}');

      if (response.statusCode != 200) {
        return EvaluationResponse(
          result: 'error',
          msg: '网络请求失败 (${response.statusCode})',
        );
      }

      final data = response.data;
      if (data is Map<String, dynamic>) {
        return EvaluationResponse(
          result: data['result']?.toString() ?? 'error',
          msg: data['msg']?.toString() ?? '未知错误',
        );
      }

      return EvaluationResponse(result: 'error', msg: '响应格式错误');
    } catch (e) {
      print('❌ Submit evaluation error: $e');
      return EvaluationResponse(result: 'error', msg: '请求异常: $e');
    }
  }
}

/// 评价响应
class EvaluationResponse {
  final String result;
  final String msg;

  EvaluationResponse({required this.result, required this.msg});

  bool get isSuccess => result == 'success';
}
