import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lunchpick/domain/repositories/settings_repository.dart';
import 'package:lunchpick/domain/entities/user_settings.dart';
import 'package:lunchpick/presentation/providers/di_providers.dart';

/// 재방문 금지 일수 Provider
final daysToExcludeProvider = FutureProvider<int>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.getDaysToExclude();
});

/// 우천시 최대 거리 Provider
final maxDistanceRainyProvider = FutureProvider<int>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.getMaxDistanceRainy();
});

/// 평상시 최대 거리 Provider
final maxDistanceNormalProvider = FutureProvider<int>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.getMaxDistanceNormal();
});

/// 알림 지연 시간 Provider
final notificationDelayMinutesProvider = FutureProvider<int>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.getNotificationDelayMinutes();
});

/// 알림 활성화 여부 Provider
final notificationEnabledProvider = FutureProvider<bool>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.isNotificationEnabled();
});

/// 스크린샷 모드 활성화 여부 Provider
final screenshotModeEnabledProvider = FutureProvider<bool>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.isScreenshotModeEnabled();
});

/// 다크모드 활성화 여부 Provider
final darkModeEnabledProvider = FutureProvider<bool>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.isDarkModeEnabled();
});

/// 첫 실행 여부 Provider
final isFirstRunProvider = FutureProvider<bool>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.isFirstRun();
});

/// 설정 스트림 Provider
final settingsStreamProvider = StreamProvider<Map<String, dynamic>>((ref) {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.watchSettings();
});

/// UserSettings Provider
final userSettingsProvider = FutureProvider<UserSettings>((ref) async {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.getUserSettings();
});

/// UserSettings 스트림 Provider
final userSettingsStreamProvider = StreamProvider<UserSettings>((ref) {
  final repository = ref.watch(settingsRepositoryProvider);
  return repository.watchUserSettings();
});

/// 설정 관리 StateNotifier
class SettingsNotifier extends StateNotifier<AsyncValue<void>> {
  final SettingsRepository _repository;

  SettingsNotifier(this._repository) : super(const AsyncValue.data(null));

  /// 재방문 금지 일수 설정
  Future<void> setDaysToExclude(int days) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setDaysToExclude(days);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 우천시 최대 거리 설정
  Future<void> setMaxDistanceRainy(int meters) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setMaxDistanceRainy(meters);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 평상시 최대 거리 설정
  Future<void> setMaxDistanceNormal(int meters) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setMaxDistanceNormal(meters);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 알림 지연 시간 설정
  Future<void> setNotificationDelayMinutes(int minutes) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setNotificationDelayMinutes(minutes);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 알림 활성화 설정
  Future<void> setNotificationEnabled(bool enabled) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setNotificationEnabled(enabled);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 스크린샷 모드 설정
  Future<void> setScreenshotModeEnabled(bool enabled) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setScreenshotModeEnabled(enabled);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 다크모드 설정
  Future<void> setDarkModeEnabled(bool enabled) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setDarkModeEnabled(enabled);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 첫 실행 상태 업데이트
  Future<void> setFirstRun(bool isFirst) async {
    state = const AsyncValue.loading();
    try {
      await _repository.setFirstRun(isFirst);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 설정 초기화
  Future<void> resetSettings() async {
    state = const AsyncValue.loading();
    try {
      await _repository.resetSettings();
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// UserSettings 업데이트
  Future<void> updateUserSettings(UserSettings settings) async {
    state = const AsyncValue.loading();
    try {
      await _repository.updateUserSettings(settings);
      state = const AsyncValue.data(null);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }
}

/// SettingsNotifier Provider
final settingsNotifierProvider =
    StateNotifierProvider<SettingsNotifier, AsyncValue<void>>((ref) {
      final repository = ref.watch(settingsRepositoryProvider);
      return SettingsNotifier(repository);
    });

/// 설정 프리셋
enum SettingsPreset {
  normal(
    name: '일반 모드',
    daysToExclude: 7,
    maxDistanceNormal: 1000,
    maxDistanceRainy: 500,
  ),
  economic(
    name: '절약 모드',
    daysToExclude: 3,
    maxDistanceNormal: 500,
    maxDistanceRainy: 300,
  ),
  convenience(
    name: '편의 모드',
    daysToExclude: 14,
    maxDistanceNormal: 2000,
    maxDistanceRainy: 1000,
  );

  final String name;
  final int daysToExclude;
  final int maxDistanceNormal;
  final int maxDistanceRainy;

  const SettingsPreset({
    required this.name,
    required this.daysToExclude,
    required this.maxDistanceNormal,
    required this.maxDistanceRainy,
  });
}

/// 프리셋 적용 Provider
final applyPresetProvider = Provider.family<Future<void>, SettingsPreset>((
  ref,
  preset,
) async {
  final notifier = ref.read(settingsNotifierProvider.notifier);

  await notifier.setDaysToExclude(preset.daysToExclude);
  await notifier.setMaxDistanceNormal(preset.maxDistanceNormal);
  await notifier.setMaxDistanceRainy(preset.maxDistanceRainy);
});

/// 현재 위치 Provider
final currentLocationProvider =
    StateProvider<({double latitude, double longitude})?>((ref) => null);

/// 선호 카테고리 Provider
final preferredCategoriesProvider = StateProvider<List<String>>((ref) => []);

/// 제외 카테고리 Provider
final excludedCategoriesProvider = StateProvider<List<String>>((ref) => []);

/// 언어 설정 Provider
final languageProvider = StateProvider<String>((ref) => 'ko');

/// 위치 권한 상태 Provider
final locationPermissionProvider = StateProvider<bool>((ref) => false);

/// 알림 권한 상태 Provider
final notificationPermissionProvider = StateProvider<bool>((ref) => false);

/// 모든 설정 상태를 통합한 Provider
final allSettingsProvider = Provider<Map<String, dynamic>>((ref) {
  final daysToExclude = ref.watch(daysToExcludeProvider).value ?? 7;
  final maxDistanceRainy = ref.watch(maxDistanceRainyProvider).value ?? 500;
  final maxDistanceNormal = ref.watch(maxDistanceNormalProvider).value ?? 1000;
  final notificationDelay =
      ref.watch(notificationDelayMinutesProvider).value ?? 90;
  final notificationEnabled =
      ref.watch(notificationEnabledProvider).value ?? false;
  final darkMode = ref.watch(darkModeEnabledProvider).value ?? false;
  final currentLocation = ref.watch(currentLocationProvider);
  final preferredCategories = ref.watch(preferredCategoriesProvider);
  final excludedCategories = ref.watch(excludedCategoriesProvider);
  final language = ref.watch(languageProvider);

  return {
    'daysToExclude': daysToExclude,
    'maxDistanceRainy': maxDistanceRainy,
    'maxDistanceNormal': maxDistanceNormal,
    'notificationDelayMinutes': notificationDelay,
    'notificationEnabled': notificationEnabled,
    'darkModeEnabled': darkMode,
    'currentLocation': currentLocation,
    'preferredCategories': preferredCategories,
    'excludedCategories': excludedCategories,
    'language': language,
  };
});
