/// Failure classes for error handling in the Worker app
///
/// Failures represent domain-level errors that can be returned from use cases
/// and repositories. They wrap exceptions and provide user-friendly error messages.
library;

/// Base failure class
sealed class Failure {
  const Failure({required this.message});

  /// Network-related failure
  const factory Failure.network({required String message, int? statusCode}) =
      NetworkFailure;

  /// Server error failure (5xx errors)
  const factory Failure.server({required String message, int? statusCode}) =
      ServerFailure;

  /// Authentication failure
  const factory Failure.authentication({
    required String message,
    int? statusCode,
  }) = AuthenticationFailure;

  /// Validation failure
  const factory Failure.validation({
    required String message,
    Map<String, List<String>>? errors,
  }) = ValidationFailure;

  /// Not found failure (404)
  const factory Failure.notFound({required String message}) = NotFoundFailure;

  /// Conflict failure (409)
  const factory Failure.conflict({required String message}) = ConflictFailure;

  /// Rate limit exceeded failure (429)
  const factory Failure.rateLimit({required String message, int? retryAfter}) =
      RateLimitFailure;

  /// Payment failure
  const factory Failure.payment({
    required String message,
    String? transactionId,
  }) = PaymentFailure;

  /// Cache failure
  const factory Failure.cache({required String message}) = CacheFailure;

  /// Storage failure
  const factory Failure.storage({required String message}) = StorageFailure;

  /// Parse failure
  const factory Failure.parse({required String message}) = ParseFailure;

  /// No internet connection failure
  const factory Failure.noInternet() = NoInternetFailure;

  /// Timeout failure
  const factory Failure.timeout() = TimeoutFailure;

  /// Unknown failure
  const factory Failure.unknown({required String message}) = UnknownFailure;

  final String message;

  /// Check if this is a critical failure that requires immediate attention
  bool get isCritical {
    return switch (this) {
      ServerFailure() => true,
      AuthenticationFailure() => true,
      PaymentFailure() => true,
      UnknownFailure() => true,
      _ => false,
    };
  }

  /// Check if this failure can be retried
  bool get canRetry {
    return switch (this) {
      NetworkFailure() => true,
      ServerFailure(:final statusCode) => statusCode == 503,
      AuthenticationFailure(:final statusCode) => statusCode == 401,
      RateLimitFailure() => true,
      CacheFailure() => true,
      NoInternetFailure() => true,
      TimeoutFailure() => true,
      _ => false,
    };
  }

  /// Get HTTP status code if available
  int? get statusCode {
    return switch (this) {
      NetworkFailure(:final statusCode) => statusCode,
      ServerFailure(:final statusCode) => statusCode,
      AuthenticationFailure(:final statusCode) => statusCode,
      _ => null,
    };
  }

  /// Get user-friendly error message
  String getUserMessage() {
    return switch (this) {
      ValidationFailure(:final message, :final errors) =>
        _formatValidationMessage(message, errors),
      RateLimitFailure(:final message, :final retryAfter) =>
        _formatRateLimitMessage(message, retryAfter),
      NoInternetFailure() =>
        'Không có kết nối internet. Vui lòng kiểm tra kết nối của bạn.',
      TimeoutFailure() => 'Kết nối quá lâu. Vui lòng thử lại.',
      _ => message,
    };
  }

  String _formatValidationMessage(
    String message,
    Map<String, List<String>>? errors,
  ) {
    if (errors != null && errors.isNotEmpty) {
      final firstError = errors.values.first.first;
      return '$message: $firstError';
    }
    return message;
  }

  String _formatRateLimitMessage(String message, int? retryAfter) {
    if (retryAfter != null) {
      return '$message Thử lại sau $retryAfter giây.';
    }
    return message;
  }
}

/// Network-related failure
final class NetworkFailure extends Failure {
  const NetworkFailure({required super.message, this.statusCode});

  @override
  final int? statusCode;
}

/// Server error failure (5xx errors)
final class ServerFailure extends Failure {
  const ServerFailure({required super.message, this.statusCode});

  @override
  final int? statusCode;
}

/// Authentication failure
final class AuthenticationFailure extends Failure {
  const AuthenticationFailure({required super.message, this.statusCode});

  @override
  final int? statusCode;
}

/// Validation failure
final class ValidationFailure extends Failure {
  const ValidationFailure({required super.message, this.errors});

  final Map<String, List<String>>? errors;
}

/// Not found failure (404)
final class NotFoundFailure extends Failure {
  const NotFoundFailure({required super.message});
}

/// Conflict failure (409)
final class ConflictFailure extends Failure {
  const ConflictFailure({required super.message});
}

/// Rate limit exceeded failure (429)
final class RateLimitFailure extends Failure {
  const RateLimitFailure({required super.message, this.retryAfter});

  final int? retryAfter;
}

/// Payment failure
final class PaymentFailure extends Failure {
  const PaymentFailure({required super.message, this.transactionId});

  final String? transactionId;
}

/// Cache failure
final class CacheFailure extends Failure {
  const CacheFailure({required super.message});
}

/// Storage failure
final class StorageFailure extends Failure {
  const StorageFailure({required super.message});
}

/// Parse failure
final class ParseFailure extends Failure {
  const ParseFailure({required super.message});
}

/// No internet connection failure
final class NoInternetFailure extends Failure {
  const NoInternetFailure() : super(message: 'Không có kết nối internet');
}

/// Timeout failure
final class TimeoutFailure extends Failure {
  const TimeoutFailure() : super(message: 'Kết nối quá lâu');
}

/// Unknown failure
final class UnknownFailure extends Failure {
  const UnknownFailure({required super.message});
}
