// ABOUTME: States for health data BLoC to represent different loading and data states
// ABOUTME: Defines all possible states that health data can be in throughout the app lifecycle
import 'package:equatable/equatable.dart';
import 'package:albi/models/health_data.dart';
import 'package:albi/models/weight_entry.dart';
import 'package:albi/models/blood_pressure_entry.dart';
import 'package:albi/models/mood_entry.dart';

/// Base class for all health data states
abstract class HealthDataState extends Equatable {
  const HealthDataState();

  @override
  List<Object?> get props => [];
}

/// Initial state before any operations
class HealthDataInitial extends HealthDataState {
  const HealthDataInitial();
}

/// Loading state during database operations
class HealthDataLoading extends HealthDataState {
  final String? message;

  const HealthDataLoading({this.message});

  @override
  List<Object?> get props => [message];
}

/// Loaded state with all data successfully retrieved
class HealthDataLoaded extends HealthDataState {
  final Map<String, List<HealthData>> recentEntries;
  final List<WeightEntry> weightEntries;
  final List<BloodPressureEntry> bloodPressureEntries;
  final List<MoodEntry> moodEntries;
  final Map<String, int> entryCounts;
  final WeightEntry? latestWeight;
  final BloodPressureEntry? latestBloodPressure;
  final MoodEntry? latestMood;
  final double? weightTrend;

  const HealthDataLoaded({
    this.recentEntries = const {},
    this.weightEntries = const [],
    this.bloodPressureEntries = const [],
    this.moodEntries = const [],
    this.entryCounts = const {},
    this.latestWeight,
    this.latestBloodPressure,
    this.latestMood,
    this.weightTrend,
  });

  /// Helper method to check if any data exists
  bool get hasData =>
      weightEntries.isNotEmpty ||
      bloodPressureEntries.isNotEmpty ||
      moodEntries.isNotEmpty ||
      latestWeight != null ||
      latestBloodPressure != null ||
      latestMood != null;

  /// Helper method to get total entry count
  int get totalEntries =>
      (entryCounts['weight'] ?? 0) +
      (entryCounts['bloodPressure'] ?? 0) +
      (entryCounts['mood'] ?? 0);

  /// Copy with method for state updates
  HealthDataLoaded copyWith({
    Map<String, List<HealthData>>? recentEntries,
    List<WeightEntry>? weightEntries,
    List<BloodPressureEntry>? bloodPressureEntries,
    List<MoodEntry>? moodEntries,
    Map<String, int>? entryCounts,
    WeightEntry? latestWeight,
    BloodPressureEntry? latestBloodPressure,
    MoodEntry? latestMood,
    double? weightTrend,
  }) {
    return HealthDataLoaded(
      recentEntries: recentEntries ?? this.recentEntries,
      weightEntries: weightEntries ?? this.weightEntries,
      bloodPressureEntries: bloodPressureEntries ?? this.bloodPressureEntries,
      moodEntries: moodEntries ?? this.moodEntries,
      entryCounts: entryCounts ?? this.entryCounts,
      latestWeight: latestWeight ?? this.latestWeight,
      latestBloodPressure: latestBloodPressure ?? this.latestBloodPressure,
      latestMood: latestMood ?? this.latestMood,
      weightTrend: weightTrend ?? this.weightTrend,
    );
  }

  @override
  List<Object?> get props => [
        recentEntries,
        weightEntries,
        bloodPressureEntries,
        moodEntries,
        entryCounts,
        latestWeight,
        latestBloodPressure,
        latestMood,
        weightTrend,
      ];
}

/// Error state with error information
class HealthDataError extends HealthDataState {
  final String message;
  final String? details;
  final bool canRetry;
  final String? errorCode;
  final String? suggestedAction;
  final ErrorSeverity severity;

  const HealthDataError({
    required this.message,
    this.details,
    this.canRetry = true,
    this.errorCode,
    this.suggestedAction,
    this.severity = ErrorSeverity.error,
  });

  /// Create a validation error
  const HealthDataError.validation({
    required this.message,
    this.details,
    this.suggestedAction = 'Please correct the highlighted fields and try again',
  }) : canRetry = false,
       errorCode = 'VALIDATION_ERROR',
       severity = ErrorSeverity.warning;

  /// Create a database error
  const HealthDataError.database({
    required this.message,
    this.details,
    this.canRetry = true,
    this.suggestedAction = 'Please try again or restart the app',
  }) : errorCode = 'DATABASE_ERROR',
       severity = ErrorSeverity.error;

  /// Create a network error
  const HealthDataError.network({
    required this.message,
    this.details,
    this.canRetry = true,
    this.suggestedAction = 'Check your internet connection and try again',
  }) : errorCode = 'NETWORK_ERROR',
       severity = ErrorSeverity.warning;

  /// Create a critical error
  const HealthDataError.critical({
    required this.message,
    this.details,
    this.canRetry = false,
    this.suggestedAction = 'Please restart the app',
  }) : errorCode = 'CRITICAL_ERROR',
       severity = ErrorSeverity.critical;

  @override
  List<Object?> get props => [message, details, canRetry, errorCode, suggestedAction, severity];
}

/// Error severity levels
enum ErrorSeverity {
  info,
  warning,
  error,
  critical,
}

/// Operation success state (for add, update, delete operations)
class HealthDataOperationSuccess extends HealthDataState {
  final String message;
  final String operationType;

  const HealthDataOperationSuccess({
    required this.message,
    required this.operationType,
  });

  @override
  List<Object> get props => [message, operationType];
}

/// Data refreshing state (when pulling to refresh)
class HealthDataRefreshing extends HealthDataState {
  final HealthDataLoaded currentData;

  const HealthDataRefreshing(this.currentData);

  @override
  List<Object> get props => [currentData];
}

/// Empty state when no data exists
class HealthDataEmpty extends HealthDataState {
  final String message;

  const HealthDataEmpty({
    this.message = 'No health data found. Start tracking by adding your first entry.',
  });

  @override
  List<Object> get props => [message];
}
