import 'package:mypoint_flutter_app/app/config/constants.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import '../../core/network/restful_api_viewmodel.dart';

class QRPackageCodeValue {
  final String type;
  final String length;
  final String value;

  const QRPackageCodeValue({required this.type, required this.length, required this.value});
}

class QRCodeViewModel extends RestfulApiViewModel {
  void Function(String message)? onShowAlertError;

  Future<void> getDirectionFromId(String id) async {
    showLoading();
    final response = await client.getDirectionOfflineBrand(id);
    final direction = response.data;
    if (response.isSuccess && direction != null) {
      hideLoading();
      final directionSuccess = direction.begin();
      if (directionSuccess != true) {
        onShowAlertError?.call(ErrorCodes.serverErrorMessage);
      } else {
        onShowAlertError?.call('');
      }
    } else {
      hideLoading();
      onShowAlertError?.call(response.errorMessage ?? ErrorCodes.serverErrorMessage);
    }
  }

  int _crc16CcittEmv(List<int> bytes) {
    const poly = 0x1021;
    var crc = 0xFFFF;
    for (final b in bytes) {
      crc ^= (b & 0xFF) << 8;
      for (var i = 0; i < 8; i++) {
        final carry = (crc & 0x8000) != 0;
        crc = (crc << 1) & 0xFFFF;
        if (carry) crc ^= poly;
      }
    }
    return crc & 0xFFFF;
  }

  bool emvCrcValid(String full, String crcHexFromPayload) {
    final idx = full.lastIndexOf('63');
    if (idx < 0 || idx + 4 > full.length) return false; // không có "63" + "LEN"
    final lenStr = full.substring(idx + 2, idx + 4);
    final len = int.tryParse(lenStr) ?? 0;
    if (len != 4) return false;

    // dữ liệu tham gia CRC: từ đầu → sau "63" + "04" (không gồm value CRC)
    final data = full.substring(0, idx + 4);
    final crc = _crc16CcittEmv(data.codeUnits)
        .toRadixString(16)
        .toUpperCase()
        .padLeft(4, '0');
    return crc == crcHexFromPayload.toUpperCase();
  }

  QRPackageCodeValue? _findByType(List<QRPackageCodeValue> list, String type) {
    for (final e in list) {
      if (e.type == type) return e;
    }
    return null;
  }

  String? getResultCodeID(String code) {
    final codes = getPackageCode(code);

    final crcField = _findByType(codes, '63');
    final merchantAccountInfo = _findByType(codes, '38');
    if (crcField == null || merchantAccountInfo == null) return null;
    if (!emvCrcValid(code, crcField.value)) return null;

    final merchantInfoValue = getPackageCode(merchantAccountInfo.value);
    final merchantIdInfo = _findByType(merchantInfoValue, '01');
    if (merchantIdInfo == null) return null;

    final merchantData = getPackageCode(merchantIdInfo.value);
    final bankIdField = _findByType(merchantData, '01');
    return bankIdField?.value;
  }

  List<QRPackageCodeValue> getPackageCode(String input) {
    final codes = <QRPackageCodeValue>[];
    var s = input;
    while (s.isNotEmpty) {
      if (s.length < 4) break;
      final id = s.substring(0, 2);
      s = s.substring(2);

      final lenStr = s.substring(0, 2);
      s = s.substring(2);

      final len = int.tryParse(lenStr) ?? 0;
      if (len < 0 || s.length < len) break;

      final value = s.substring(0, len);
      s = s.substring(len);

      codes.add(QRPackageCodeValue(type: id, length: lenStr, value: value));
    }
    return codes;
  }
}