import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'app_logger.dart';
import 'exceptions.dart';

/// Global error handler for the application
class ErrorHandler {
  static final ErrorHandler _instance = ErrorHandler._internal();
  factory ErrorHandler() => _instance;
  ErrorHandler._internal();

  final AppLogger _logger = AppLogger();
  bool _isInitialized = false;

  /// Initialize global error handling
  void initialize() {
    if (_isInitialized) return;

    // Capture Flutter framework errors
    FlutterError.onError = (FlutterErrorDetails details) {
      _handleFlutterError(details);
    };

    // Capture errors in platform-specific code
    PlatformDispatcher.instance.onError = (error, stack) {
      _handlePlatformError(error, stack);
      return true;
    };

    _isInitialized = true;
    _logger.info('Global error handler initialized');
  }

  /// Run the app with error zone guarding
  static Future<void> runAppWithErrorHandling(
    Future<void> Function() appRunner,
  ) async {
    final errorHandler = ErrorHandler();
    errorHandler.initialize();

    // Run app in a guarded zone to catch async errors
    await runZonedGuarded(
      () async {
        await appRunner();
      },
      (error, stackTrace) {
        errorHandler._handleZoneError(error, stackTrace);
      },
    );
  }

  /// Handle Flutter framework errors
  void _handleFlutterError(FlutterErrorDetails details) {
    // Log the error
    _logger.error(
      'Flutter Error',
      error: details.exception,
      stackTrace: details.stack,
    );

    // In debug mode, show the red error screen
    if (kDebugMode) {
      FlutterError.presentError(details);
    }

    // Optionally report to crash reporting service
    _reportError(details.exception, details.stack);
  }

  /// Handle platform-specific errors
  bool _handlePlatformError(Object error, StackTrace stackTrace) {
    _logger.error('Platform Error', error: error, stackTrace: stackTrace);

    _reportError(error, stackTrace);
    return true;
  }

  /// Handle errors from runZonedGuarded
  void _handleZoneError(Object error, StackTrace stackTrace) {
    _logger.error('Async Error', error: error, stackTrace: stackTrace);

    _reportError(error, stackTrace);
  }

  /// Report error to external service (optional)
  void _reportError(Object error, StackTrace? stackTrace) {
    // In production, you could send errors to services like:
    // - Firebase Crashlytics
    // - Sentry
    // - Custom error reporting endpoint

    if (kReleaseMode) {
      // TODO: Implement error reporting to external service
      // Example: FirebaseCrashlytics.instance.recordError(error, stackTrace);
    }
  }

  /// Handle and display user-friendly error messages
  static String getUserFriendlyMessage(Object error) {
    if (error is AppException) {
      return error.message;
    } else if (error is NetworkException) {
      return '网络连接失败，请检查网络设置';
    } else if (error is AuthenticationException) {
      return '登录失败，请检查账号密码';
    } else if (error is ParseException) {
      return '数据解析失败，请稍后重试';
    } else if (error is ValidationException) {
      return '输入验证失败：${error.message}';
    } else if (error is TimeoutException) {
      return '请求超时，请稍后重试';
    } else if (error is FormatException) {
      return '数据格式错误';
    } else {
      return '发生未知错误，请稍后重试';
    }
  }

  /// Show error dialog to user
  static void showErrorDialog(
    BuildContext context,
    Object error, {
    VoidCallback? onRetry,
  }) {
    final message = getUserFriendlyMessage(error);

    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('错误'),
        content: Text(message),
        actions: [
          if (onRetry != null)
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
                onRetry();
              },
              child: const Text('重试'),
            ),
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('确定'),
          ),
        ],
      ),
    );
  }

  /// Show error snackbar to user
  static void showErrorSnackBar(
    BuildContext context,
    Object error, {
    Duration duration = const Duration(seconds: 3),
  }) {
    final message = getUserFriendlyMessage(error);

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        duration: duration,
        backgroundColor: Colors.red,
        action: SnackBarAction(
          label: '关闭',
          textColor: Colors.white,
          onPressed: () {
            ScaffoldMessenger.of(context).hideCurrentSnackBar();
          },
        ),
      ),
    );
  }
}
