// SPDX-FileCopyrightText: © 2025 Nøkken.io <nokken.io@proton.me>
// SPDX-License-Identifier: AGPL-3.0
//
//  mood_entry.dart
//  Model for mood tracking entries
//
import 'package:uuid/uuid.dart';

/// Represents different mood ratings
enum MoodRating {
  great,
  good,
  okay,
  meh,
  bad,
}

/// Represents different emotions that can be selected
enum Emotion {
  excited,
  relaxed,
  happy,
  hot,
  hopeful,
  calm,
  grateful,
  proud,
  tired,
  sad,
  angry,
  anxious,
  stressed,
  bored,
  lonely,
  sick,
}

/// Represents sleep quality levels
enum SleepQuality {
  excellent,
  good,
  fair,
  poor,
}

/// Represents energy levels
enum EnergyLevel {
  high,
  moderate,
  low,
  depleted,
}

/// Represents libido levels
enum LibidoLevel {
  high,
  normal,
  low,
  none,
}

/// Represents appetite or eating habits
enum AppetiteLevel {
  increased,
  normal,
  decreased,
  none,
}

/// Represents focus ability
enum FocusLevel {
  sharp,
  normal,
  distracted,
  unfocused,
}

/// Represents dysphoria levels
enum DysphoriaLevel {
  none,
  mild,
  moderate,
  severe,
}

/// Represents exercise levels
enum ExerciseLevel {
  intense,
  moderate,
  light,
  none,
}

/// Extension to add helpful methods to MoodRating enum
extension MoodRatingExtension on MoodRating {
  String get displayName {
    switch (this) {
      case MoodRating.great:
        return 'Great';
      case MoodRating.good:
        return 'Good';
      case MoodRating.okay:
        return 'Okay';
      case MoodRating.meh:
        return 'Meh';
      case MoodRating.bad:
        return 'Bad';
    }
  }

  String get emoji {
    switch (this) {
      case MoodRating.great:
        return '😁';
      case MoodRating.good:
        return '🙂';
      case MoodRating.okay:
        return '😐';
      case MoodRating.meh:
        return '😕';
      case MoodRating.bad:
        return '😭';
    }
  }

  String get description {
    switch (this) {
      case MoodRating.great:
        return 'Having an amazing day!';
      case MoodRating.good:
        return 'Having a good day';
      case MoodRating.okay:
        return 'Day is going okay';
      case MoodRating.meh:
        return 'Not the best day';
      case MoodRating.bad:
        return 'Having a difficult day';
    }
  }
}

/// Extension to add helpful methods to Emotion enum
extension EmotionExtension on Emotion {
  String get displayName {
    switch (this) {
      case Emotion.excited:
        return 'Excited';
      case Emotion.relaxed:
        return 'Relaxed';
      case Emotion.happy:
        return 'Happy';
      case Emotion.hopeful:
        return 'Hopeful';
      case Emotion.calm:
        return 'Calm';
      case Emotion.grateful:
        return 'Grateful';
      case Emotion.proud:
        return 'Proud';
      case Emotion.tired:
        return 'Tired';
      case Emotion.sad:
        return 'Sad';
      case Emotion.angry:
        return 'Angry';
      case Emotion.anxious:
        return 'Anxious';
      case Emotion.stressed:
        return 'Stressed';
      case Emotion.bored:
        return 'Bored';
      case Emotion.lonely:
        return 'Lonely';
      case Emotion.hot:
        return 'Hot';
      case Emotion.sick:
        return 'Sick';
    }
  }

  String get emoji {
    switch (this) {
      case Emotion.excited:
        return '🤩';
      case Emotion.relaxed:
        return '😌';
      case Emotion.happy:
        return '😊';
      case Emotion.hopeful:
        return '🌈';
      case Emotion.calm:
        return '😇';
      case Emotion.grateful:
        return '🙏';
      case Emotion.proud:
        return '🏆';
      case Emotion.tired:
        return '😴';
      case Emotion.sad:
        return '😢';
      case Emotion.angry:
        return '😡';
      case Emotion.anxious:
        return '😰';
      case Emotion.stressed:
        return '😫';
      case Emotion.bored:
        return '🥱';
      case Emotion.lonely:
        return '🥺';
      case Emotion.hot:
        return '🔥';
      case Emotion.sick:
        return '🤧';
    }
  }
}

/// Extension for SleepQuality enum
extension SleepQualityExtension on SleepQuality {
  String get displayName {
    switch (this) {
      case SleepQuality.excellent:
        return 'Excellent';
      case SleepQuality.good:
        return 'Good';
      case SleepQuality.fair:
        return 'Fair';
      case SleepQuality.poor:
        return 'Poor';
    }
  }

  String get emoji {
    switch (this) {
      case SleepQuality.excellent:
        return '😵';
      case SleepQuality.good:
        return '😴';
      case SleepQuality.fair:
        return '😌';
      case SleepQuality.poor:
        return '🥱';
    }
  }
}

/// Extension for EnergyLevel enum
extension EnergyLevelExtension on EnergyLevel {
  String get displayName {
    switch (this) {
      case EnergyLevel.high:
        return 'High';
      case EnergyLevel.moderate:
        return 'Normal';
      case EnergyLevel.low:
        return 'Low';
      case EnergyLevel.depleted:
        return 'Fatigued';
    }
  }

  String get emoji {
    switch (this) {
      case EnergyLevel.high:
        return '⚡';
      case EnergyLevel.moderate:
        return '🔋';
      case EnergyLevel.low:
        return '🪫';
      case EnergyLevel.depleted:
        return '😴';
    }
  }
}

/// Extension for LibidoLevel enum
extension LibidoLevelExtension on LibidoLevel {
  String get displayName {
    switch (this) {
      case LibidoLevel.high:
        return 'High';
      case LibidoLevel.normal:
        return 'Normal';
      case LibidoLevel.low:
        return 'Low';
      case LibidoLevel.none:
        return 'None';
    }
  }

  String get emoji {
    switch (this) {
      case LibidoLevel.high:
        return '❤️‍🔥';
      case LibidoLevel.normal:
        return '❤️';
      case LibidoLevel.low:
        return '💔';
      case LibidoLevel.none:
        return '🤍';
    }
  }
}

/// Extension for AppetiteLevel enum
extension AppetiteLevelExtension on AppetiteLevel {
  String get displayName {
    switch (this) {
      case AppetiteLevel.increased:
        return 'Increased';
      case AppetiteLevel.normal:
        return 'Normal';
      case AppetiteLevel.decreased:
        return 'Decreased';
      case AppetiteLevel.none:
        return 'None';
    }
  }

  String get emoji {
    switch (this) {
      case AppetiteLevel.increased:
        return '🍽️';
      case AppetiteLevel.normal:
        return '🍲';
      case AppetiteLevel.decreased:
        return '🥄';
      case AppetiteLevel.none:
        return '🚫';
    }
  }
}

/// Extension for FocusLevel enum
extension FocusLevelExtension on FocusLevel {
  String get displayName {
    switch (this) {
      case FocusLevel.sharp:
        return 'Sharp';
      case FocusLevel.normal:
        return 'Normal';
      case FocusLevel.distracted:
        return 'Distracted';
      case FocusLevel.unfocused:
        return 'Unfocused';
    }
  }

  String get emoji {
    switch (this) {
      case FocusLevel.sharp:
        return '🔍';
      case FocusLevel.normal:
        return '👁️';
      case FocusLevel.distracted:
        return '🧠';
      case FocusLevel.unfocused:
        return '💫';
    }
  }
}

/// Extension for DysphoriaLevel enum
extension DysphoriaLevelExtension on DysphoriaLevel {
  String get displayName {
    switch (this) {
      case DysphoriaLevel.none:
        return 'None';
      case DysphoriaLevel.mild:
        return 'Mild';
      case DysphoriaLevel.moderate:
        return 'Moderate';
      case DysphoriaLevel.severe:
        return 'Severe';
    }
  }

  String get emoji {
    switch (this) {
      case DysphoriaLevel.none:
        return '✨';
      case DysphoriaLevel.mild:
        return '🪞';
      case DysphoriaLevel.moderate:
        return '⚠️';
      case DysphoriaLevel.severe:
        return '🚨';
    }
  }
}

/// Extension for ExerciseLevel enum
extension ExerciseLevelExtension on ExerciseLevel {
  String get displayName {
    switch (this) {
      case ExerciseLevel.intense:
        return 'Intense';
      case ExerciseLevel.moderate:
        return 'Moderate';
      case ExerciseLevel.light:
        return 'Light';
      case ExerciseLevel.none:
        return 'None';
    }
  }

  String get emoji {
    switch (this) {
      case ExerciseLevel.intense:
        return '🏋️';
      case ExerciseLevel.moderate:
        return '🚴';
      case ExerciseLevel.light:
        return '🚶';
      case ExerciseLevel.none:
        return '🛋️';
    }
  }
}

/// Custom exception for mood-related errors
class MoodEntryException implements Exception {
  final String message;
  MoodEntryException(this.message);

  @override
  String toString() => 'MoodEntryException: $message';
}

/// Primary model for mood tracking entries
class MoodEntry {
  final String id;
  final DateTime date;
  final MoodRating mood;
  final Set<Emotion> emotions;
  final String? notes;

  // New health categories
  final SleepQuality? sleepQuality;
  final EnergyLevel? energyLevel;
  final LibidoLevel? libidoLevel;
  final AppetiteLevel? appetiteLevel;
  final FocusLevel? focusLevel;
  final DysphoriaLevel? dysphoriaLevel;
  final ExerciseLevel? exerciseLevel;

  /// Constructor with validation
  MoodEntry({
    String? id,
    required this.date,
    required this.mood,
    required this.emotions,
    this.notes,
    this.sleepQuality,
    this.energyLevel,
    this.libidoLevel,
    this.appetiteLevel,
    this.focusLevel,
    this.dysphoriaLevel,
    this.exerciseLevel,
  }) : id = id ?? const Uuid().v4() {
    _validate();
  }

  /// Validates mood entry fields
  void _validate() {
    // Add any validation logic here if needed
    if (emotions.length > 10) {
      throw MoodEntryException('Maximum of 10 emotions can be selected');
    }
  }

  /// Convert to JSON format for database storage
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'date': date.toIso8601String(),
      'mood': mood.toString(),
      'emotions': emotions.map((e) => e.toString()).toList(),
      'notes': notes,
      'sleepQuality': sleepQuality?.toString(),
      'energyLevel': energyLevel?.toString(),
      'libidoLevel': libidoLevel?.toString(),
      'appetiteLevel': appetiteLevel?.toString(),
      'focusLevel': focusLevel?.toString(),
      'dysphoriaLevel': dysphoriaLevel?.toString(),
      'exerciseLevel': exerciseLevel?.toString(),
    };
  }

  /// Create a MoodEntry instance from JSON (database record)
  factory MoodEntry.fromJson(Map<String, dynamic> json) {
    try {
      // Parse mood from string (this should stay required with a default)
      final moodStr = json['mood'] as String;
      final mood = MoodRating.values.firstWhere(
        (e) => e.toString() == moodStr,
        orElse: () => MoodRating.okay, // Keep default for required field
      );

      // Parse emotions from string list
      final emotionStrList = json['emotions'] as List<dynamic>;
      final emotions = emotionStrList
          .map((emotionStr) {
            try {
              return Emotion.values.firstWhere(
                (e) => e.toString() == emotionStr,
              );
            } catch (_) {
              // Skip invalid emotions
              return null;
            }
          })
          .where((e) => e != null)
          .cast<Emotion>()
          .toSet();

      // Parse the health categories without defaults
      SleepQuality? sleepQuality;
      if (json['sleepQuality'] != null) {
        try {
          sleepQuality = SleepQuality.values.firstWhere(
            (e) => e.toString() == json['sleepQuality'],
          );
        } catch (_) {
          // If value doesn't match any enum, keep it null
          sleepQuality = null;
        }
      }

      // Repeat the same pattern for other categories
      EnergyLevel? energyLevel;
      if (json['energyLevel'] != null) {
        try {
          energyLevel = EnergyLevel.values.firstWhere(
            (e) => e.toString() == json['energyLevel'],
          );
        } catch (_) {
          energyLevel = null;
        }
      }

      // Similar pattern for the rest of the optional categories
      LibidoLevel? libidoLevel;
      if (json['libidoLevel'] != null) {
        try {
          libidoLevel = LibidoLevel.values.firstWhere(
            (e) => e.toString() == json['libidoLevel'],
          );
        } catch (_) {
          libidoLevel = null;
        }
      }

      AppetiteLevel? appetiteLevel;
      if (json['appetiteLevel'] != null) {
        try {
          appetiteLevel = AppetiteLevel.values.firstWhere(
            (e) => e.toString() == json['appetiteLevel'],
          );
        } catch (_) {
          appetiteLevel = null;
        }
      }

      FocusLevel? focusLevel;
      if (json['focusLevel'] != null) {
        try {
          focusLevel = FocusLevel.values.firstWhere(
            (e) => e.toString() == json['focusLevel'],
          );
        } catch (_) {
          focusLevel = null;
        }
      }

      DysphoriaLevel? dysphoriaLevel;
      if (json['dysphoriaLevel'] != null) {
        try {
          dysphoriaLevel = DysphoriaLevel.values.firstWhere(
            (e) => e.toString() == json['dysphoriaLevel'],
          );
        } catch (_) {
          dysphoriaLevel = null;
        }
      }

      ExerciseLevel? exerciseLevel;
      if (json['exerciseLevel'] != null) {
        try {
          exerciseLevel = ExerciseLevel.values.firstWhere(
            (e) => e.toString() == json['exerciseLevel'],
          );
        } catch (_) {
          exerciseLevel = null;
        }
      }

      return MoodEntry(
        id: json['id'] as String,
        date: DateTime.parse(json['date'] as String),
        mood: mood,
        emotions: emotions,
        notes: json['notes'] as String?,
        sleepQuality: sleepQuality,
        energyLevel: energyLevel,
        libidoLevel: libidoLevel,
        appetiteLevel: appetiteLevel,
        focusLevel: focusLevel,
        dysphoriaLevel: dysphoriaLevel,
        exerciseLevel: exerciseLevel,
      );
    } catch (e) {
      throw MoodEntryException('Invalid mood entry data: $e');
    }
  }

  /// Create a copy of this mood entry with updated fields
  MoodEntry copyWith({
    DateTime? date,
    MoodRating? mood,
    Set<Emotion>? emotions,
    String? notes,
    SleepQuality? sleepQuality,
    EnergyLevel? energyLevel,
    LibidoLevel? libidoLevel,
    AppetiteLevel? appetiteLevel,
    FocusLevel? focusLevel,
    DysphoriaLevel? dysphoriaLevel,
    ExerciseLevel? exerciseLevel,
  }) {
    return MoodEntry(
      id: id,
      date: date ?? this.date,
      mood: mood ?? this.mood,
      emotions: emotions ?? this.emotions,
      notes: notes ?? this.notes,
      sleepQuality: sleepQuality ?? this.sleepQuality,
      energyLevel: energyLevel ?? this.energyLevel,
      libidoLevel: libidoLevel ?? this.libidoLevel,
      appetiteLevel: appetiteLevel ?? this.appetiteLevel,
      focusLevel: focusLevel ?? this.focusLevel,
      dysphoriaLevel: dysphoriaLevel ?? this.dysphoriaLevel,
      exerciseLevel: exerciseLevel ?? this.exerciseLevel,
    );
  }
}
