import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import '../models/user_profile.dart';
import '../models/cycle_entry.dart';

import '../services/cycle_service.dart';
import '../services/sync_service.dart';
import 'prayer_provider.dart';
import 'teaching_plan_provider.dart';
import '../models/prayer_request.dart';
import '../models/teaching_plan.dart';

/// Provider for the user profile
final userProfileProvider =
    StateNotifierProvider<UserProfileNotifier, UserProfile?>((ref) {
  return UserProfileNotifier();
});

/// Notifier for the user profile
class UserProfileNotifier extends StateNotifier<UserProfile?> {
  UserProfileNotifier() : super(null) {
    _loadProfile();
  }

  void _loadProfile() {
    final box = Hive.box<UserProfile>('user_profile_v2');
    state = box.get('current_user');
  }

  Future<void> updateProfile(UserProfile profile) async {
    final box = Hive.box<UserProfile>('user_profile_v2');
    await box.put('current_user', profile);
    state = profile;
  }

  Future<void> updateThemeMode(AppThemeMode themeMode) async {
    if (state != null) {
      await updateProfile(state!.copyWith(themeMode: themeMode));
    }
  }

  Future<void> updateAccentColor(String accentColor) async {
    if (state != null) {
      await updateProfile(state!.copyWith(accentColor: accentColor));
    }
  }

  Future<void> updateRelationshipStatus(
      RelationshipStatus relationshipStatus) async {
    if (state != null) {
      await updateProfile(
          state!.copyWith(relationshipStatus: relationshipStatus));
    }
  }

  Future<void> clearProfile() async {
    final box = Hive.box<UserProfile>('user_profile_v2');
    await box.clear();
    state = null;
  }
}

/// Provider for cycle entries
final cycleEntriesProvider =
    StateNotifierProvider<CycleEntriesNotifier, List<CycleEntry>>((ref) {
  return CycleEntriesNotifier(ref);
});

/// Notifier for cycle entries
class CycleEntriesNotifier extends StateNotifier<List<CycleEntry>> {
  final Ref ref;
  Timer? _syncTimer;

  CycleEntriesNotifier(this.ref) : super([]) {
    _loadEntries();
    syncData(); // Auto-sync on load

    // Start periodic sync every 10 seconds
    _syncTimer = Timer.periodic(const Duration(seconds: 10), (timer) {
      _pull();
    });
  }

  @override
  void dispose() {
    _syncTimer?.cancel();
    super.dispose();
  }

  void _loadEntries() {
    final box = Hive.box<CycleEntry>('cycle_entries_v2');
    state = box.values.toList()..sort((a, b) => b.date.compareTo(a.date));
  }

  Future<void> addEntry(CycleEntry entry) async {
    final box = Hive.box<CycleEntry>('cycle_entries_v2');
    await box.put(entry.id, entry);
    _loadEntries();
    _push();
  }

  Future<void> updateEntry(CycleEntry entry) async {
    final box = Hive.box<CycleEntry>('cycle_entries_v2');
    await box.put(entry.id, entry);
    _loadEntries();
    _push();
  }

  Future<void> deleteEntry(String id) async {
    final box = Hive.box<CycleEntry>('cycle_entries_v2');
    await box.delete(id);
    _loadEntries();
    _push();
  }

  Future<void> deleteEntriesForMonth(int year, int month) async {
    final box = Hive.box<CycleEntry>('cycle_entries_v2');
    final keysToDelete = <dynamic>[];
    for (var entry in box.values) {
      if (entry.date.year == year && entry.date.month == month) {
        keysToDelete.add(entry.key);
      }
    }
    await box.deleteAll(keysToDelete);
    _loadEntries();
    _push();
  }

  Future<void> clearEntries() async {
    final box = Hive.box<CycleEntry>('cycle_entries_v2');
    await box.clear();
    state = [];
    _push();
  }

  // Sync Logic

  Future<void> syncData() async {
    await _pull();
    // After pull, we might want to push any local changes not in remote?
    // For now, simpler consistency: Pull then Push current state?
    // Or just Pull. Push happens on edit.
    // Let's just Pull.
  }

  Future<void> _push() async {
    final userBox = Hive.box<UserProfile>('user_profile_v2');
    final user = userBox.get('current_user');

    // Read current state from other providers
    // Note: This relies on the providers being initialized.
    final plans = ref.read(teachingPlansProvider);
    final prayers = ref.read(prayerRequestsProvider);

    if (user != null) {
      final userDetails = {
        'name': user.name,
        'role': user.role.name,
        'partnerId': user.partnerId,
        'createdAt': user.createdAt.toIso8601String(),
        // Add other relevant fields if needed for display on partner's side
      };

      await SyncService().pushSyncData(
        userId: user.id,
        entries: state,
        teachingPlans: plans,
        prayerRequests: prayers,
        userDetails: userDetails,
      );
    }
  }

  Future<void> _pull() async {
    final userBox = Hive.box<UserProfile>('user_profile_v2');
    final user = userBox.get('current_user');
    if (user == null) return;

    final syncResult = await SyncService().pullSyncData(
      user.id,
      partnerId: user.partnerId,
    );

    // 0. Check for Server-Side Profile Updates (Auto-Link)
    if (syncResult.containsKey('userProfile')) {
      final serverProfile = syncResult['userProfile'] as Map<String, dynamic>;
      final serverPartnerId = serverProfile['partnerId'];

      // If server has a partner ID and we don't (or it's different), update!
      if (serverPartnerId != null && serverPartnerId != user.partnerId) {
        // Update local profile
        final updatedProfile = user.copyWith(partnerId: serverPartnerId);
        await Hive.box<UserProfile>('user_profile_v2')
            .put('current_user', updatedProfile);

        // Refresh provider state if needed, but important is to RE-SYNC with new ID
        // so we get the partner's data immediately.
        return _pull(); // Recursive call will now use new partnerId
      }
    }

    final remoteEntries = syncResult['entries'] as List<CycleEntry>? ?? [];
    final remotePlans =
        syncResult['teachingPlans'] as List<TeachingPlan>? ?? [];
    final remotePrayers =
        syncResult['prayerRequests'] as List<PrayerRequest>? ?? [];

    // 1. Cycle Entries
    if (remoteEntries.isNotEmpty) {
      final box = Hive.box<CycleEntry>('cycle_entries_v2');
      // Simple merge: remote wins for id collisions
      for (var entry in remoteEntries) {
        await box.put(entry.id, entry);
      }
      _loadEntries();
    }

    // 2. Teaching Plans
    if (remotePlans.isNotEmpty) {
      final box = Hive.box<TeachingPlan>('teaching_plans_v2');
      for (var plan in remotePlans) {
        await box.put(plan.id, plan);
      }
      // Refresh provider
      ref.invalidate(teachingPlansProvider);
    }

    // 3. Prayer Requests
    if (remotePrayers.isNotEmpty) {
      final box = Hive.box<PrayerRequest>('prayer_requests_v2');
      for (var req in remotePrayers) {
        await box.put(req.id, req);
      }
      // Refresh provider
      ref.invalidate(prayerRequestsProvider);
    }
  }

  // Example data generation removed
}

/// Computed provider for current cycle info
final currentCycleInfoProvider = Provider((ref) {
  final user = ref.watch(userProfileProvider);
  final entries = ref.watch(cycleEntriesProvider);
  return CycleService.calculateCycleInfo(user, entries);
});
