import 'dart:math';
import 'dart:developer' as dev;
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../shared/data/local/app_database.dart';
import '../../../shared/data/repositories/user_repository.dart';
import '../data/repositories/quest_repository.dart';

enum QuestTrigger {
  workoutComplete,
  volume,
  repCount,
  inventoryChange,
}

final questServiceProvider = Provider<QuestService>((ref) {
  final questRepo = ref.watch(questRepositoryProvider);
  final userRepo = ref.watch(userRepositoryProvider);
  return QuestService(ref: ref, questRepo: questRepo, userRepo: userRepo);
});

class QuestService {
  final Ref ref;
  final QuestRepository questRepo;
  final UserRepository userRepo;

  QuestService({
    required this.ref,
    required this.questRepo,
    required this.userRepo,
  });

  Future<void> checkAndGenerateQuests() async {
    await _cleanupExpired();
    await _generateDailiesIfNeeded();
    await _ensureStoryQuests();
  }

  Future<void> _cleanupExpired() async {
    await questRepo.cleanupExpiredQuests();
  }

  Future<void> _generateDailiesIfNeeded() async {
    final activeDailies = await questRepo.getActiveQuests();
    final hasDailies = activeDailies.any((q) => q.type == 'daily');

    if (!hasDailies) {
      dev.log('🎲 Generating new Daily Quests...');
      final random = Random();
      final newQuests = <QuestCollection>[];

      final pool = List<_QuestTemplate>.from(_dailyQuestPool)..shuffle();
      final selected = pool.take(3);

      final now = DateTime.now();
      final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59);

      for (var template in selected) {
        newQuests.add(QuestCollection(
          id: 'daily_${now.millisecondsSinceEpoch}_${random.nextInt(1000)}',
          type: 'daily',
          title: template.title,
          description: template.description,
          targetValue: template.target,
          currentValue: 0,
          rewardXP: template.xp,
          rewardItem: template.itemId,
          isCompleted: false,
          isClaimed: false,
          expiresAt: endOfDay,
          createdAt: now,
        ));
      }

      for (var q in newQuests) {
        await questRepo.createQuest(q);
      }
    }
  }

  Future<void> _ensureStoryQuests() async {
    final activeQuests = await questRepo.getActiveQuests();

    // Helper: Prüft ob Quest-ID schon existiert (aktiv oder erledigt)
    // Hinweis: getActiveQuests liefert aktuell alle nicht-abgelaufenen.
    // Für Story Quests (die nie ablaufen) reicht das.
    bool hasQuest(String id) => activeQuests.any((q) => q.id == id);

    if (!hasQuest('story_initiate')) {
      await questRepo.createQuest(QuestCollection(
        id: 'story_initiate',
        type: 'story',
        title: 'The Awakening',
        description: 'Complete your first workout to prove your worth.',
        targetValue: 1,
        currentValue: 0,
        rewardXP: 100,
        isCompleted: false,
        isClaimed: false,
        createdAt: DateTime.now(),
      ));
    }

    if (!hasQuest('story_inventory')) {
      await questRepo.createQuest(QuestCollection(
        id: 'story_inventory',
        type: 'story',
        title: 'Armory Master',
        description: 'Setup your equipment inventory.',
        targetValue: 1,
        currentValue: 0,
        rewardXP: 50,
        isCompleted: false,
        isClaimed: false,
        createdAt: DateTime.now(),
      ));
      final inventory = await userRepo.getInventorySettingsAsync();
      if ((inventory['plates'] as List).isNotEmpty) {
        await questRepo.updateProgress('story_inventory', 1);
      }
    }
  }

  Future<void> reportEvent(QuestTrigger trigger, {dynamic data}) async {
    final activeQuests = await questRepo.getActiveQuests();

    for (var quest in activeQuests) {
      if (quest.isCompleted) continue;

      if (quest.id == 'story_initiate' &&
          trigger == QuestTrigger.workoutComplete) {
        await questRepo.updateProgress(quest.id, 1);
      }

      if (quest.title == 'Volume Eater' && trigger == QuestTrigger.volume) {
        final volume = data as int; // kg
        await questRepo.updateProgress(quest.id, volume);
      }

      if (quest.title == 'Workout Warrior' &&
          trigger == QuestTrigger.workoutComplete) {
        await questRepo.updateProgress(quest.id, 1);
      }

      if (quest.title == 'Rep Collector' && trigger == QuestTrigger.repCount) {
        final reps = data as int;
        await questRepo.updateProgress(quest.id, reps);
      }
    }
  }
}

class _QuestTemplate {
  final String title;
  final String description;
  final int target;
  final int xp;
  final String? itemId;

  const _QuestTemplate(this.title, this.description, this.target, this.xp,
      [this.itemId]);
}

const List<_QuestTemplate> _dailyQuestPool = [
  _QuestTemplate(
      'Volume Eater', 'Move a total of 500kg in a single day.', 500, 100),
  _QuestTemplate('Workout Warrior', 'Complete 1 Workout today.', 1, 50),
  _QuestTemplate('Rep Collector',
      'Perform 50 total repetitions across all exercises.', 50, 75),
  _QuestTemplate('Early Bird', 'Start a workout before noon.', 1, 50),
  _QuestTemplate(
      'Iron Discipline', 'Log your bodyweight in the profile.', 1, 25),
];
