// SPDX-FileCopyrightText: © 2025 Nøkken.io <nokken.io@proton.me>
// SPDX-License-Identifier: AGPL-3.0
//
// mood_data_generator.dart
//
import 'dart:math' show Random;
import 'package:flutter/material.dart';
import 'package:nokken/src/core/services/database/database_service.dart';
import 'package:nokken/src/core/services/database/database_service_mood.dart';
import 'package:nokken/src/features/mood_tracker/models/mood_entry.dart';
import 'package:uuid/uuid.dart';

/// A tool class to generate historical mood data
class MoodDataGenerator {
  final DatabaseService databaseService;

  MoodDataGenerator(this.databaseService);

  /// Generate 365 days of mood entries
  Future<void> generateMoodEntries() async {
    final random = Random();

    // Start date: 364 days ago from today
    final endDate = DateTime.now();
    final startDate = endDate.subtract(const Duration(days: 364));

    debugPrint(
        'Generating mood entries from ${startDate.toIso8601String()} to ${endDate.toIso8601String()}');

    // Generate an entry for each day
    for (int i = 0; i <= 364; i++) {
      final date = startDate.add(Duration(days: i));

      // Generate random mood entry
      final entry = _generateRandomMoodEntry(date, random);

      // Insert into database
      await databaseService.insertMoodEntry(entry);

      // Print progress
      if (i % 30 == 0) {
        debugPrint('Generated ${i + 1} entries...');
      }
    }

    debugPrint('Successfully generated 365 mood entries.');
  }

  /// Generate a random but realistic mood entry for the given date
  MoodEntry _generateRandomMoodEntry(DateTime date, Random random) {
    // Generate a unique ID
    final id = const Uuid().v4();

    // Generate a base mood index with some weekly and seasonal patterns
    int baseMoodModifier = 0;

    // Weekday effects: people often feel better on weekends, worse on Mondays
    if (date.weekday == DateTime.saturday || date.weekday == DateTime.sunday) {
      baseMoodModifier =
          random.nextDouble() < 0.7 ? 1 : 0; // Better mood on weekends
    } else if (date.weekday == DateTime.monday) {
      baseMoodModifier =
          random.nextDouble() < 0.6 ? -1 : 0; // Worse mood on Mondays
    }

    // Seasonal effects: worse in winter, better in summer
    final month = date.month;
    int seasonalModifier = 0;
    if (month >= 11 || month <= 2) {
      // Winter months
      seasonalModifier = random.nextDouble() < 0.6 ? -1 : 0;
    } else if (month >= 5 && month <= 8) {
      // Summer months
      seasonalModifier = random.nextDouble() < 0.6 ? 1 : 0;
    }

    // Calculate final mood index with modifiers and randomness
    // Assuming mood from terrible (0) to excellent (4)
    int moodIndex =
        2 + baseMoodModifier + seasonalModifier; // Start from neutral (2)
    moodIndex += (random.nextInt(3) - 1); // Add -1, 0, or 1 for randomness
    moodIndex = moodIndex.clamp(0, 4); // Ensure within valid range

    // Convert index to actual MoodRating enum
    final mood = MoodRating.values[moodIndex];

    // Generate 1-6 random emotions
    final emotionCount = random.nextInt(6) + 1;
    final emotions = <Emotion>{};
    while (emotions.length < emotionCount &&
        emotions.length < Emotion.values.length) {
      final emotionIndex = random.nextInt(Emotion.values.length);
      emotions.add(Emotion.values[emotionIndex]);
    }

    // Decide which health metrics to include (3 to all)
    final healthMetricsCount = random.nextInt(5) + 3; // 3 to 7 metrics
    final healthMetricsToInclude = List.generate(7, (index) => index)
      ..shuffle(random);
    final selectedHealthMetrics =
        healthMetricsToInclude.take(healthMetricsCount).toList();

    // Helper function to generate a correlated index
    int correlatedIndex(
        int baseIndex, double correlationStrength, int maxIndex) {
      if (random.nextDouble() < correlationStrength) {
        // Correlated value
        final variation = random.nextInt(3) - 1; // -1, 0, or 1
        return (baseIndex + variation).clamp(0, maxIndex - 1);
      } else {
        // Random value
        return random.nextInt(maxIndex);
      }
    }

    // Generate health metrics
    SleepQuality? sleepQuality;
    EnergyLevel? energyLevel;
    LibidoLevel? libidoLevel;
    AppetiteLevel? appetiteLevel;
    FocusLevel? focusLevel;
    DysphoriaLevel? dysphoriaLevel;
    ExerciseLevel? exerciseLevel;

    // Sleep quality - somewhat correlated with mood
    if (selectedHealthMetrics.contains(0)) {
      final sleepIndex =
          correlatedIndex(moodIndex, 0.7, SleepQuality.values.length);
      sleepQuality = SleepQuality.values[sleepIndex];
    }

    // Energy level - often follows sleep quality if available
    if (selectedHealthMetrics.contains(1)) {
      int energyIndex;
      if (sleepQuality != null && random.nextDouble() < 0.8) {
        // Correlate with sleep
        energyIndex = correlatedIndex(SleepQuality.values.indexOf(sleepQuality),
            0.8, EnergyLevel.values.length);
      } else {
        // Correlate with mood
        energyIndex =
            correlatedIndex(moodIndex, 0.6, EnergyLevel.values.length);
      }
      energyLevel = EnergyLevel.values[energyIndex];
    }

    // Libido level - moderately correlated with mood
    if (selectedHealthMetrics.contains(2)) {
      final libidoIndex =
          correlatedIndex(moodIndex, 0.5, LibidoLevel.values.length);
      libidoLevel = LibidoLevel.values[libidoIndex];
    }

    // Appetite level - less correlated with mood
    if (selectedHealthMetrics.contains(3)) {
      final appetiteIndex =
          correlatedIndex(moodIndex, 0.4, AppetiteLevel.values.length);
      appetiteLevel = AppetiteLevel.values[appetiteIndex];
    }

    // Focus level - often correlates with sleep and energy
    if (selectedHealthMetrics.contains(4)) {
      int focusIndex;
      if (sleepQuality != null &&
          energyLevel != null &&
          random.nextDouble() < 0.7) {
        // Derive from average of sleep and energy
        final avgIndex = (SleepQuality.values.indexOf(sleepQuality) +
                EnergyLevel.values.indexOf(energyLevel)) ~/
            2;
        focusIndex = correlatedIndex(avgIndex, 0.8, FocusLevel.values.length);
      } else {
        // Correlate with mood
        focusIndex = correlatedIndex(moodIndex, 0.6, FocusLevel.values.length);
      }
      focusLevel = FocusLevel.values[focusIndex];
    }

    // Dysphoria level - often inversely correlates with mood
    if (selectedHealthMetrics.contains(5)) {
      // Invert the mood index for dysphoria correlation (higher mood = lower dysphoria)
      final invertedMood = 4 - moodIndex; // Assuming 5 mood levels (0-4)
      final dysphoriaIndex =
          correlatedIndex(invertedMood, 0.75, DysphoriaLevel.values.length);
      dysphoriaLevel = DysphoriaLevel.values[dysphoriaIndex];
    }

    // Exercise level - less strongly correlated with other metrics
    if (selectedHealthMetrics.contains(6)) {
      final exerciseIndex = random.nextInt(ExerciseLevel.values.length);
      exerciseLevel = ExerciseLevel.values[exerciseIndex];
    }

    // Generate optional notes (30% chance)
    String? notes;
    if (random.nextDouble() < 0.3) {
      final noteTemplates = [
        "Feeling ${moodIndex > 2 ? 'pretty good' : 'a bit down'} today.",
        "Today was ${moodIndex > 3 ? 'excellent' : moodIndex > 2 ? 'decent' : 'challenging'}.",
        "${moodIndex > 3 ? 'Great' : moodIndex > 2 ? 'Good' : 'Tough'} day overall.",
        "Noticed ${sleepQuality != null ? (SleepQuality.values.indexOf(sleepQuality) > 2 ? 'good sleep' : 'poor sleep') : 'fluctuating energy'} today.",
        "Mood tracker note for ${date.day}/${date.month}/${date.year}.",
        "${energyLevel != null && EnergyLevel.values.indexOf(energyLevel) > 2 ? 'High energy' : 'Low energy'} but ${moodIndex > 2 ? 'good spirits' : 'feeling down'}.",
        "Trying to stay ${moodIndex < 2 ? 'positive despite challenges' : 'grateful for the good things'}.",
      ];

      notes = noteTemplates[random.nextInt(noteTemplates.length)];
    }

    // Create and return the mood entry
    return MoodEntry(
      id: id,
      date: date,
      mood: mood,
      emotions: emotions,
      notes: notes,
      sleepQuality: sleepQuality,
      energyLevel: energyLevel,
      libidoLevel: libidoLevel,
      appetiteLevel: appetiteLevel,
      focusLevel: focusLevel,
      dysphoriaLevel: dysphoriaLevel,
      exerciseLevel: exerciseLevel,
    );
  }
}
