import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'sentry_config.dart';

/// Sentry 服务
/// 封装崩溃收集、错误上报、性能监控等功能
class SentryService {
  static SentryService? _instance;
  SentryService._();

  factory SentryService() {
    _instance ??= SentryService._();
    return _instance!;
  }

  bool _isInitialized = false;
  bool get isInitialized => _isInitialized;

  SentryConfig? _config;
  SentryConfig? get config => _config;

  /// 用户ID (登录后设置)
  String? _userId;

  /// 初始化 Sentry
  /// 必须在 runApp 之前调用
  static Future<void> init({
    required SentryConfig config,
    required AppRunner appRunner,
  }) async {
    if (config.dsn.isEmpty || !config.enabled) {
      debugPrint('[Sentry] Sentry is disabled');
      await appRunner();
      return;
    }

    // 在调试模式下检查是否启用
    if (kDebugMode && !config.enableInDebug) {
      debugPrint('[Sentry] Sentry is disabled in debug mode');
      await appRunner();
      return;
    }

    await SentryFlutter.init(
      (options) {
        options.dsn = config.dsn;
        options.environment = config.environment;
        options.release = config.release;

        // 采样率
        options.sampleRate = config.sampleRate;
        options.tracesSampleRate = config.tracesSampleRate;

        // 功能开关
        options.enableAutoPerformanceTracing = config.enablePerformance;
        options.enableUserInteractionTracing = config.enablePerformance;
        options.enableAutoNativeBreadcrumbs = config.enableBreadcrumbs;
        options.maxBreadcrumbs = config.maxBreadcrumbs;
        options.sendDefaultPii = config.sendDefaultPii;

        // 调试
        options.debug = kDebugMode;

        // 附加信息
        options.attachStacktrace = true;
        options.attachScreenshot = true;
        options.attachViewHierarchy = true;

        // 过滤敏感信息
        options.beforeSend = _beforeSend;
        options.beforeBreadcrumb = _beforeBreadcrumb;
      },
      appRunner: appRunner,
    );

    SentryService()._config = config;
    SentryService()._isInitialized = true;
    debugPrint('[Sentry] Initialized successfully');
    debugPrint('[Sentry]   Environment: ${config.environment}');
    debugPrint('[Sentry]   Sample Rate: ${config.sampleRate}');
  }

  /// 发送事件前的钩子 (可过滤敏感信息)
  static SentryEvent? _beforeSend(SentryEvent event, Hint hint) {
    // 过滤掉包含敏感信息的事件
    final message = event.message?.formatted ?? '';
    if (_containsSensitiveData(message)) {
      return null;
    }

    // 过滤异常信息中的敏感数据
    if (event.exceptions != null) {
      for (final exception in event.exceptions!) {
        if (_containsSensitiveData(exception.value ?? '')) {
          return null;
        }
      }
    }

    return event;
  }

  /// 面包屑前的钩子 (可过滤敏感操作)
  static Breadcrumb? _beforeBreadcrumb(Breadcrumb? breadcrumb, Hint hint) {
    if (breadcrumb == null) return null;

    // 过滤掉敏感路径的导航
    final category = breadcrumb.category ?? '';
    final data = breadcrumb.data ?? {};

    // 过滤密码相关页面
    if (category == 'navigation') {
      final route = data['to'] as String? ?? '';
      if (route.contains('password') || route.contains('mnemonic')) {
        return null;
      }
    }

    // 过滤敏感 HTTP 请求
    if (category == 'http') {
      final url = data['url'] as String? ?? '';
      if (url.contains('auth') || url.contains('token')) {
        // 移除敏感数据但保留请求记录
        return breadcrumb.copyWith(
          data: {'url': _sanitizeUrl(url), 'method': data['method']},
        );
      }
    }

    return breadcrumb;
  }

  /// 检查是否包含敏感数据
  static bool _containsSensitiveData(String text) {
    final sensitivePatterns = [
      RegExp(r'password', caseSensitive: false),
      RegExp(r'mnemonic', caseSensitive: false),
      RegExp(r'private.?key', caseSensitive: false),
      RegExp(r'secret', caseSensitive: false),
      RegExp(r'bearer\s+[\w-]+', caseSensitive: false),
    ];

    for (final pattern in sensitivePatterns) {
      if (pattern.hasMatch(text)) {
        return true;
      }
    }
    return false;
  }

  /// 清理 URL 中的敏感参数
  static String _sanitizeUrl(String url) {
    try {
      final uri = Uri.parse(url);
      final sanitizedParams = <String, String>{};
      uri.queryParameters.forEach((key, value) {
        if (_isSensitiveParam(key)) {
          sanitizedParams[key] = '[REDACTED]';
        } else {
          sanitizedParams[key] = value;
        }
      });
      return uri.replace(queryParameters: sanitizedParams).toString();
    } catch (_) {
      return url;
    }
  }

  /// 检查是否是敏感参数
  static bool _isSensitiveParam(String key) {
    final sensitiveKeys = ['token', 'password', 'secret', 'key', 'auth'];
    return sensitiveKeys.any((k) => key.toLowerCase().contains(k));
  }

  // ========== 用户信息 ==========

  /// 设置用户信息 (登录后调用)
  void setUser({
    required String userId,
    String? email,
    String? username,
    Map<String, dynamic>? extras,
  }) {
    if (!_isInitialized) return;

    _userId = userId;
    Sentry.configureScope((scope) {
      scope.setUser(SentryUser(
        id: userId,
        email: email,
        username: username,
        data: extras,
      ));
    });
    debugPrint('[Sentry] User set: $userId');
  }

  /// 清除用户信息 (退出登录时调用)
  void clearUser() {
    if (!_isInitialized) return;

    _userId = null;
    Sentry.configureScope((scope) {
      scope.setUser(null);
    });
    debugPrint('[Sentry] User cleared');
  }

  // ========== 错误上报 ==========

  /// 捕获异常
  Future<SentryId> captureException(
    dynamic exception, {
    dynamic stackTrace,
    String? message,
    Map<String, dynamic>? extras,
    SentryLevel? level,
  }) async {
    if (!_isInitialized) return SentryId.empty();

    return await Sentry.captureException(
      exception,
      stackTrace: stackTrace,
      withScope: (scope) {
        if (message != null) {
          scope.setContexts('error_context', {'message': message});
        }
        if (extras != null) {
          scope.setContexts('extras', extras);
        }
        if (level != null) {
          scope.level = level;
        }
      },
    );
  }

  /// 捕获消息 (非异常的错误/警告)
  Future<SentryId> captureMessage(
    String message, {
    SentryLevel level = SentryLevel.info,
    Map<String, dynamic>? extras,
  }) async {
    if (!_isInitialized) return SentryId.empty();

    return await Sentry.captureMessage(
      message,
      level: level,
      withScope: (scope) {
        if (extras != null) {
          scope.setContexts('extras', extras);
        }
      },
    );
  }

  // ========== 面包屑 (用户操作轨迹) ==========

  /// 添加面包屑
  void addBreadcrumb({
    required String message,
    String? category,
    Map<String, dynamic>? data,
    SentryLevel level = SentryLevel.info,
  }) {
    if (!_isInitialized) return;

    Sentry.addBreadcrumb(Breadcrumb(
      message: message,
      category: category,
      data: data,
      level: level,
      timestamp: DateTime.now(),
    ));
  }

  /// 添加导航面包屑
  void addNavigationBreadcrumb({
    required String from,
    required String to,
  }) {
    addBreadcrumb(
      message: 'Navigation: $from -> $to',
      category: 'navigation',
      data: {'from': from, 'to': to},
    );
  }

  /// 添加 HTTP 请求面包屑
  void addHttpBreadcrumb({
    required String url,
    required String method,
    int? statusCode,
    String? reason,
  }) {
    addBreadcrumb(
      message: '$method $url',
      category: 'http',
      data: {
        'url': _sanitizeUrl(url),
        'method': method,
        if (statusCode != null) 'status_code': statusCode,
        if (reason != null) 'reason': reason,
      },
      level: (statusCode != null && statusCode >= 400)
          ? SentryLevel.error
          : SentryLevel.info,
    );
  }

  /// 添加用户操作面包屑
  void addUserActionBreadcrumb({
    required String action,
    String? target,
    Map<String, dynamic>? data,
  }) {
    addBreadcrumb(
      message: action,
      category: 'user_action',
      data: {
        if (target != null) 'target': target,
        ...?data,
      },
    );
  }

  // ========== 上下文信息 ==========

  /// 设置额外上下文
  void setContext(String key, Map<String, dynamic> value) {
    if (!_isInitialized) return;

    Sentry.configureScope((scope) {
      scope.setContexts(key, value);
    });
  }

  /// 设置标签
  void setTag(String key, String value) {
    if (!_isInitialized) return;

    Sentry.configureScope((scope) {
      scope.setTag(key, value);
    });
  }

  /// 设置设备信息
  void setDeviceContext({
    String? deviceId,
    String? deviceModel,
    String? osVersion,
    String? appVersion,
  }) {
    setContext('device_info', {
      if (deviceId != null) 'device_id': deviceId,
      if (deviceModel != null) 'device_model': deviceModel,
      if (osVersion != null) 'os_version': osVersion,
      if (appVersion != null) 'app_version': appVersion,
    });
  }

  // ========== 性能监控 ==========

  /// 开始事务 (用于性能追踪)
  ISentrySpan? startTransaction({
    required String name,
    required String operation,
    String? description,
  }) {
    if (!_isInitialized || _config?.enablePerformance != true) return null;

    return Sentry.startTransaction(
      name,
      operation,
      description: description,
      bindToScope: true,
    );
  }

  /// 包装异步操作并追踪性能
  Future<T> traceAsync<T>({
    required String name,
    required String operation,
    required Future<T> Function() fn,
  }) async {
    final transaction = startTransaction(name: name, operation: operation);

    try {
      final result = await fn();
      transaction?.status = const SpanStatus.ok();
      return result;
    } catch (e) {
      transaction?.status = const SpanStatus.internalError();
      transaction?.throwable = e;
      rethrow;
    } finally {
      await transaction?.finish();
    }
  }

  // ========== 用户反馈 ==========

  /// 收集用户反馈
  Future<void> captureUserFeedback({
    required SentryId eventId,
    required String comments,
    String? email,
    String? name,
  }) async {
    if (!_isInitialized || _config?.enableUserFeedback != true) return;

    await Sentry.captureFeedback(SentryFeedback(
      message: comments,
      contactEmail: email,
      name: name,
      associatedEventId: eventId,
    ));
  }

  // ========== 工具方法 ==========

  /// 获取当前用户ID
  String? get userId => _userId;

  /// 强制上传所有待发送事件
  Future<void> flush() async {
    if (!_isInitialized) return;
    // Sentry SDK 会自动处理上传，这里可以添加额外逻辑
  }

  /// 关闭 Sentry
  Future<void> close() async {
    if (!_isInitialized) return;
    await Sentry.close();
    _isInitialized = false;
    debugPrint('[Sentry] Closed');
  }

  /// 重置实例 (用于测试)
  static void reset() {
    _instance = null;
  }
}
