import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../network/api_client.dart';

/// 合同签署状态
enum ContractSigningStatus {
  pending,         // 待签署
  scrolled,        // 已滚动到底部
  acknowledged,    // 已确认法律效力
  signed,          // 已签署
  unsignedTimeout, // 超时未签署
}

/// 合同签署任务
class ContractSigningTask {
  final String orderNo;
  final String contractNo;
  final String accountSequence;
  final ContractSigningStatus status;
  final String contractVersion;
  final String contractContent;
  final int treeCount;
  final double totalAmount;
  final String provinceName;
  final String cityName;
  final String? userRealName; // 用户实名（用于签名参照）
  final DateTime expiresAt;
  final DateTime? scrolledToBottomAt;
  final DateTime? acknowledgedAt;
  final DateTime? signedAt;
  final String? signatureCloudUrl;
  final DateTime createdAt;

  ContractSigningTask({
    required this.orderNo,
    required this.contractNo,
    required this.accountSequence,
    required this.status,
    required this.contractVersion,
    required this.contractContent,
    required this.treeCount,
    required this.totalAmount,
    required this.provinceName,
    required this.cityName,
    this.userRealName,
    required this.expiresAt,
    this.scrolledToBottomAt,
    this.acknowledgedAt,
    this.signedAt,
    this.signatureCloudUrl,
    required this.createdAt,
  });

  factory ContractSigningTask.fromJson(Map<String, dynamic> json) {
    return ContractSigningTask(
      orderNo: json['orderNo'] ?? '',
      contractNo: json['contractNo'] ?? '',
      accountSequence: json['accountSequence'] ?? '',
      status: _parseStatus(json['status']),
      contractVersion: json['contractVersion'] ?? '',
      contractContent: json['contractContent'] ?? '',
      treeCount: json['treeCount'] ?? 0,
      totalAmount: (json['totalAmount'] ?? 0).toDouble(),
      provinceName: json['provinceName'] ?? '',
      cityName: json['cityName'] ?? '',
      userRealName: json['userRealName'],
      expiresAt: json['expiresAt'] != null
          ? DateTime.parse(json['expiresAt'])
          : DateTime.now().add(const Duration(hours: 24)),
      scrolledToBottomAt: json['scrolledToBottomAt'] != null
          ? DateTime.parse(json['scrolledToBottomAt'])
          : null,
      acknowledgedAt: json['acknowledgedAt'] != null
          ? DateTime.parse(json['acknowledgedAt'])
          : null,
      signedAt: json['signedAt'] != null
          ? DateTime.parse(json['signedAt'])
          : null,
      signatureCloudUrl: json['signatureCloudUrl'],
      createdAt: json['createdAt'] != null
          ? DateTime.parse(json['createdAt'])
          : DateTime.now(),
    );
  }

  static ContractSigningStatus _parseStatus(String? status) {
    switch (status) {
      case 'PENDING':
        return ContractSigningStatus.pending;
      case 'SCROLLED':
        return ContractSigningStatus.scrolled;
      case 'ACKNOWLEDGED':
        return ContractSigningStatus.acknowledged;
      case 'SIGNED':
        return ContractSigningStatus.signed;
      case 'UNSIGNED_TIMEOUT':
        return ContractSigningStatus.unsignedTimeout;
      default:
        return ContractSigningStatus.pending;
    }
  }

  /// 剩余时间（秒）
  int get remainingSeconds {
    final now = DateTime.now();
    if (now.isAfter(expiresAt)) return 0;
    return expiresAt.difference(now).inSeconds;
  }

  /// 是否已过期
  bool get isExpired => remainingSeconds <= 0;

  /// 是否需要签署（未完成且未过期）
  bool get needsSign =>
      status != ContractSigningStatus.signed &&
      status != ContractSigningStatus.unsignedTimeout;
}

/// 合同模板
class ContractTemplate {
  final String version;
  final String title;
  final String content;

  ContractTemplate({
    required this.version,
    required this.title,
    required this.content,
  });

  factory ContractTemplate.fromJson(Map<String, dynamic> json) {
    return ContractTemplate(
      version: json['version'] ?? '',
      title: json['title'] ?? '',
      content: json['content'] ?? '',
    );
  }
}

/// 合同签署配置
class ContractSigningConfig {
  /// 合同签署功能是否启用
  final bool contractSigningEnabled;

  ContractSigningConfig({
    required this.contractSigningEnabled,
  });

  factory ContractSigningConfig.fromJson(Map<String, dynamic> json) {
    return ContractSigningConfig(
      contractSigningEnabled: json['contractSigningEnabled'] ?? true,
    );
  }
}

/// KYC 需求检查结果
class KycRequirementResult {
  /// 是否需要完成 KYC
  final bool requiresKyc;

  /// 已付款但未完成 KYC 的订单数量
  final int paidOrderCount;

  /// 提示消息
  final String? message;

  KycRequirementResult({
    required this.requiresKyc,
    required this.paidOrderCount,
    this.message,
  });

  factory KycRequirementResult.fromJson(Map<String, dynamic> json) {
    return KycRequirementResult(
      requiresKyc: json['requiresKyc'] ?? false,
      paidOrderCount: json['paidOrderCount'] ?? 0,
      message: json['message'],
    );
  }
}

/// 合同签署服务
class ContractSigningService {
  final ApiClient _apiClient;

  ContractSigningService({required ApiClient apiClient}) : _apiClient = apiClient;

  /// 获取合同签署配置（公开接口，不需要认证）
  /// 用于判断是否需要在认种前检查实名认证
  Future<ContractSigningConfig> getConfig() async {
    try {
      debugPrint('[ContractSigningService] 获取合同签署配置');

      final response = await _apiClient.get('/planting/contract-signing/config');

      if (response.statusCode == 200) {
        final data = response.data as Map<String, dynamic>;
        if (data['success'] == true && data['data'] != null) {
          return ContractSigningConfig.fromJson(data['data']);
        }
      }

      // 默认启用合同签署
      return ContractSigningConfig(contractSigningEnabled: true);
    } catch (e) {
      debugPrint('[ContractSigningService] 获取配置失败: $e');
      // 获取失败时默认启用合同签署
      return ContractSigningConfig(contractSigningEnabled: true);
    }
  }

  /// 检查用户是否需要先完成 KYC
  ///
  /// 如果用户有已付款的认种订单但未完成 KYC，返回需要强制完成 KYC 的信息
  Future<KycRequirementResult> checkKycRequirement() async {
    try {
      final response = await _apiClient.get('/planting/contract-signing/kyc-requirement');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true && responseData['data'] != null) {
          final data = responseData['data'] as Map<String, dynamic>;
          return KycRequirementResult.fromJson(data);
        }
      }

      // 默认不需要 KYC
      return KycRequirementResult(requiresKyc: false, paidOrderCount: 0);
    } catch (e) {
      debugPrint('[ContractSigningService] 检查 KYC 需求失败: $e');
      // 检查失败时不阻止用户
      return KycRequirementResult(requiresKyc: false, paidOrderCount: 0);
    }
  }

  /// 获取待签署任务列表
  Future<List<ContractSigningTask>> getPendingTasks() async {
    try {
      final response = await _apiClient.get('/planting/contract-signing/pending');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true && responseData['data'] != null) {
          final data = responseData['data'] as List<dynamic>;
          return data.map((e) => ContractSigningTask.fromJson(e)).toList();
        }
        return [];
      }

      throw Exception('获取待签署任务失败: ${response.statusCode}');
    } catch (e) {
      debugPrint('[ContractSigningService] 获取待签署任务失败: $e');
      rethrow;
    }
  }

  /// 获取未签署任务列表（包括超时的）
  Future<List<ContractSigningTask>> getUnsignedTasks() async {
    try {
      final response = await _apiClient.get('/planting/contract-signing/unsigned');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true && responseData['data'] != null) {
          final data = responseData['data'] as List<dynamic>;
          return data.map((e) => ContractSigningTask.fromJson(e)).toList();
        }
        return [];
      }

      throw Exception('获取未签署任务失败: ${response.statusCode}');
    } catch (e) {
      debugPrint('[ContractSigningService] 获取未签署任务失败: $e');
      rethrow;
    }
  }

  /// 获取签署任务详情
  Future<ContractSigningTask> getTask(String orderNo) async {
    try {

      final response = await _apiClient.get('/planting/contract-signing/tasks/$orderNo');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true && responseData['data'] != null) {
          final data = responseData['data'] as Map<String, dynamic>;
          debugPrint('[ContractSigningService] 任务 expiresAt: ${data['expiresAt']}');
          return ContractSigningTask.fromJson(data);
        }
        throw Exception('获取任务失败: ${responseData['message']}');
      }

      throw Exception('获取签署任务详情失败: ${response.statusCode}');
    } catch (e) {
      debugPrint('[ContractSigningService] 获取签署任务详情失败: $e');
      rethrow;
    }
  }

  /// 标记已滚动到底部
  Future<ContractSigningTask> markScrollComplete(String orderNo) async {
    try {
      debugPrint('[ContractSigningService] 标记已滚动到底部: $orderNo');
      debugPrint('[ContractSigningService] 请求 URL: /planting/contract-signing/tasks/$orderNo/scroll-complete');

      final response = await _apiClient.post(
        '/planting/contract-signing/tasks/$orderNo/scroll-complete',
      );

      debugPrint('[ContractSigningService] 响应状态码: ${response.statusCode}');
      debugPrint('[ContractSigningService] 响应数据: ${response.data}');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true) {
          debugPrint('[ContractSigningService] 滚动标记成功');
          // 后端可能返回 data，也可能只返回 success + message
          if (responseData['data'] != null) {
            final data = responseData['data'] as Map<String, dynamic>;
            debugPrint('[ContractSigningService] 返回任务数据，状态: ${data['status']}');
            return ContractSigningTask.fromJson(data);
          }
          // 兼容直接返回任务数据的情况
          if (responseData['orderNo'] != null) {
            debugPrint('[ContractSigningService] 滚动标记成功（直接返回数据）');
            return ContractSigningTask.fromJson(responseData);
          }
          // 如果没有返回 data，重新获取任务详情
          debugPrint('[ContractSigningService] 重新获取任务详情');
          return await getTask(orderNo);
        }
        throw Exception('标记滚动失败: ${responseData['message'] ?? '响应格式错误'}');
      }

      throw Exception('标记滚动失败: ${response.statusCode}');
    } catch (e, stackTrace) {
      debugPrint('[ContractSigningService] 标记滚动失败: $e');
      debugPrint('[ContractSigningService] 堆栈: $stackTrace');
      rethrow;
    }
  }

  /// 确认法律效力
  Future<ContractSigningTask> acknowledgeContract(String orderNo) async {
    try {
      debugPrint('[ContractSigningService] 确认法律效力: $orderNo');
      debugPrint('[ContractSigningService] 请求 URL: /planting/contract-signing/tasks/$orderNo/acknowledge');

      final response = await _apiClient.post(
        '/planting/contract-signing/tasks/$orderNo/acknowledge',
      );

      debugPrint('[ContractSigningService] 响应状态码: ${response.statusCode}');
      debugPrint('[ContractSigningService] 响应数据: ${response.data}');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true) {
          debugPrint('[ContractSigningService] 确认法律效力成功');
          // 后端可能返回 data，也可能只返回 success + message
          if (responseData['data'] != null) {
            final data = responseData['data'] as Map<String, dynamic>;
            debugPrint('[ContractSigningService] 返回任务数据，状态: ${data['status']}');
            return ContractSigningTask.fromJson(data);
          }
          // 兼容直接返回任务数据的情况
          if (responseData['orderNo'] != null) {
            debugPrint('[ContractSigningService] 确认法律效力成功（直接返回数据）');
            return ContractSigningTask.fromJson(responseData);
          }
          // 如果没有返回 data，重新获取任务详情
          debugPrint('[ContractSigningService] 重新获取任务详情');
          return await getTask(orderNo);
        }
        throw Exception('确认法律效力失败: ${responseData['message'] ?? '响应格式错误'}');
      }

      throw Exception('确认法律效力失败: ${response.statusCode}');
    } catch (e, stackTrace) {
      debugPrint('[ContractSigningService] 确认法律效力失败: $e');
      debugPrint('[ContractSigningService] 堆栈: $stackTrace');
      rethrow;
    }
  }

  /// 签署合同
  Future<ContractSigningTask> signContract({
    required String orderNo,
    required Uint8List signatureImage,
    String? ipAddress,
    String? deviceInfo,
    String? userAgent,
    double? latitude,
    double? longitude,
    Map<String, dynamic>? signatureTrace, // 签名轨迹数据
  }) async {
    try {
      debugPrint('[ContractSigningService] 签署合同: $orderNo');
      debugPrint('[ContractSigningService] 签名图片大小: ${signatureImage.length} bytes');
      debugPrint('[ContractSigningService] IP: $ipAddress, 设备: $deviceInfo');
      debugPrint('[ContractSigningService] 位置: lat=$latitude, lng=$longitude');
      if (signatureTrace != null) {
        debugPrint('[ContractSigningService] 签名轨迹: ${signatureTrace['strokeCount']} 笔画, ${signatureTrace['totalDuration']}ms');
      }

      // 将签名图片转为 base64
      final signatureBase64 = base64Encode(signatureImage);
      debugPrint('[ContractSigningService] Base64 长度: ${signatureBase64.length}');

      final requestData = {
        'signatureBase64': signatureBase64,  // 后端期望的字段名
        'signatureHash': '',  // TODO: 计算签名哈希
        'deviceInfo': {
          'deviceId': deviceInfo ?? 'unknown',
          'platform': 'android',
        },
        'location': latitude != null && longitude != null
            ? {'latitude': latitude, 'longitude': longitude}
            : null,
        'signatureTrace': signatureTrace, // 签名轨迹数据
      };
      debugPrint('[ContractSigningService] 请求 URL: /planting/contract-signing/tasks/$orderNo/sign');

      final response = await _apiClient.post(
        '/planting/contract-signing/tasks/$orderNo/sign',
        data: requestData,
      );

      debugPrint('[ContractSigningService] 响应状态码: ${response.statusCode}');
      debugPrint('[ContractSigningService] 响应数据: ${response.data}');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true) {
          debugPrint('[ContractSigningService] 签署成功');
          // 后端可能返回 data，也可能只返回 success + message
          if (responseData['data'] != null) {
            final data = responseData['data'] as Map<String, dynamic>;
            debugPrint('[ContractSigningService] 返回任务数据，状态: ${data['status']}');
            return ContractSigningTask.fromJson(data);
          }
          // 如果没有返回 data，重新获取任务详情
          debugPrint('[ContractSigningService] 重新获取任务详情');
          return await getTask(orderNo);
        }
        throw Exception('签署合同失败: ${responseData['message'] ?? '响应格式错误'}');
      }

      throw Exception('签署合同失败: ${response.statusCode}');
    } catch (e, stackTrace) {
      debugPrint('[ContractSigningService] 签署合同失败: $e');
      debugPrint('[ContractSigningService] 堆栈: $stackTrace');
      rethrow;
    }
  }

  /// 补签合同（超时后）
  Future<ContractSigningTask> lateSignContract({
    required String orderNo,
    required Uint8List signatureImage,
    String? ipAddress,
    String? deviceInfo,
    String? userAgent,
    double? latitude,
    double? longitude,
    Map<String, dynamic>? signatureTrace, // 签名轨迹数据
  }) async {
    try {
      debugPrint('[ContractSigningService] 补签合同: $orderNo');
      debugPrint('[ContractSigningService] 签名图片大小: ${signatureImage.length} bytes');
      debugPrint('[ContractSigningService] IP: $ipAddress, 设备: $deviceInfo');
      debugPrint('[ContractSigningService] 位置: lat=$latitude, lng=$longitude');
      if (signatureTrace != null) {
        debugPrint('[ContractSigningService] 签名轨迹: ${signatureTrace['strokeCount']} 笔画, ${signatureTrace['totalDuration']}ms');
      }

      final signatureBase64 = base64Encode(signatureImage);
      debugPrint('[ContractSigningService] Base64 长度: ${signatureBase64.length}');

      final requestData = {
        'signatureBase64': signatureBase64,  // 后端期望的字段名
        'signatureHash': '',  // TODO: 计算签名哈希
        'deviceInfo': {
          'deviceId': deviceInfo ?? 'unknown',
          'platform': 'android',
        },
        'location': latitude != null && longitude != null
            ? {'latitude': latitude, 'longitude': longitude}
            : null,
        'signatureTrace': signatureTrace, // 签名轨迹数据
      };
      debugPrint('[ContractSigningService] 请求 URL: /planting/contract-signing/tasks/$orderNo/late-sign');

      final response = await _apiClient.post(
        '/planting/contract-signing/tasks/$orderNo/late-sign',
        data: requestData,
      );

      debugPrint('[ContractSigningService] 响应状态码: ${response.statusCode}');
      debugPrint('[ContractSigningService] 响应数据: ${response.data}');

      if (response.statusCode == 200) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['success'] == true) {
          debugPrint('[ContractSigningService] 补签成功');
          // 后端可能返回 data，也可能只返回 success + message
          if (responseData['data'] != null) {
            final data = responseData['data'] as Map<String, dynamic>;
            debugPrint('[ContractSigningService] 返回任务数据，状态: ${data['status']}');
            return ContractSigningTask.fromJson(data);
          }
          // 如果没有返回 data，重新获取任务详情
          debugPrint('[ContractSigningService] 重新获取任务详情');
          return await getTask(orderNo);
        }
        throw Exception('补签合同失败: ${responseData['message'] ?? '响应格式错误'}');
      }

      throw Exception('补签合同失败: ${response.statusCode}');
    } catch (e, stackTrace) {
      debugPrint('[ContractSigningService] 补签合同失败: $e');
      debugPrint('[ContractSigningService] 堆栈: $stackTrace');
      rethrow;
    }
  }

  /// 获取当前合同模板
  Future<ContractTemplate> getCurrentTemplate() async {
    try {
      debugPrint('[ContractSigningService] 获取当前合同模板');

      final response = await _apiClient.get('/planting/contract-signing/template');

      if (response.statusCode == 200) {
        final data = response.data as Map<String, dynamic>;
        return ContractTemplate.fromJson(data);
      }

      throw Exception('获取合同模板失败: ${response.statusCode}');
    } catch (e) {
      debugPrint('[ContractSigningService] 获取合同模板失败: $e');
      rethrow;
    }
  }

  /// 下载合同 PDF 文件
  ///
  /// [orderNo] 订单号
  /// [onProgress] 下载进度回调，参数为 (已接收字节数, 总字节数)
  /// [cancelToken] 用于取消下载的 token
  ///
  /// 特性：
  /// - 10 次自动重试
  /// - 300 秒超时
  /// - 支持进度回调
  /// - 支持取消下载
  Future<Uint8List> downloadContractPdf(
    String orderNo, {
    void Function(int received, int total)? onProgress,
    CancelToken? cancelToken,
  }) async {
    const maxRetries = 10;
    const timeout = Duration(seconds: 300);

    for (int attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        debugPrint('[ContractSigningService] 下载合同 PDF: $orderNo (尝试 $attempt/$maxRetries)');

        final response = await _apiClient.get(
          '/planting/contract-signing/tasks/$orderNo/pdf',
          options: Options(
            responseType: ResponseType.bytes,
            receiveTimeout: timeout,
          ),
          cancelToken: cancelToken,
          onReceiveProgress: onProgress,
        );

        if (response.statusCode == 200) {
          debugPrint('[ContractSigningService] PDF 下载成功，大小: ${response.data.length} bytes');
          return Uint8List.fromList(response.data);
        }

        throw Exception('下载 PDF 失败: ${response.statusCode}');
      } on DioException catch (e) {
        debugPrint('[ContractSigningService] 下载 PDF 失败 (尝试 $attempt/$maxRetries): ${e.type} - ${e.message}');

        // 如果是用户取消，直接抛出不重试
        if (e.type == DioExceptionType.cancel) {
          debugPrint('[ContractSigningService] 用户取消下载');
          rethrow;
        }

        // 最后一次尝试失败，抛出异常
        if (attempt == maxRetries) {
          debugPrint('[ContractSigningService] 已达到最大重试次数，放弃下载');
          throw Exception('下载 PDF 失败，已重试 $maxRetries 次: ${e.message}');
        }

        // 等待后重试，使用指数退避策略（2s, 4s, 6s...最大10s）
        final waitSeconds = (attempt * 2).clamp(2, 10);
        debugPrint('[ContractSigningService] 等待 ${waitSeconds}s 后重试...');
        await Future.delayed(Duration(seconds: waitSeconds));
      } catch (e) {
        debugPrint('[ContractSigningService] 下载 PDF 异常 (尝试 $attempt/$maxRetries): $e');

        if (attempt == maxRetries) {
          debugPrint('[ContractSigningService] 已达到最大重试次数，放弃下载');
          rethrow;
        }

        final waitSeconds = (attempt * 2).clamp(2, 10);
        debugPrint('[ContractSigningService] 等待 ${waitSeconds}s 后重试...');
        await Future.delayed(Duration(seconds: waitSeconds));
      }
    }

    // 理论上不会到这里，但为了类型安全
    throw Exception('下载 PDF 失败');
  }
}

/// Base64 编码函数
String base64Encode(Uint8List bytes) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  final result = StringBuffer();

  for (var i = 0; i < bytes.length; i += 3) {
    final b0 = bytes[i];
    final b1 = i + 1 < bytes.length ? bytes[i + 1] : 0;
    final b2 = i + 2 < bytes.length ? bytes[i + 2] : 0;

    result.write(chars[(b0 >> 2) & 0x3F]);
    result.write(chars[((b0 << 4) | (b1 >> 4)) & 0x3F]);

    if (i + 1 < bytes.length) {
      result.write(chars[((b1 << 2) | (b2 >> 6)) & 0x3F]);
    } else {
      result.write('=');
    }

    if (i + 2 < bytes.length) {
      result.write(chars[b2 & 0x3F]);
    } else {
      result.write('=');
    }
  }

  return result.toString();
}
