import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:geolocator/geolocator.dart';
import 'package:lunchpick/domain/entities/weather_info.dart';
import 'package:lunchpick/domain/repositories/weather_repository.dart';
import 'package:lunchpick/presentation/providers/di_providers.dart';
import 'package:lunchpick/presentation/providers/location_provider.dart';

/// 현재 날씨 Provider
final weatherProvider = FutureProvider<WeatherInfo>((ref) async {
  final repository = ref.watch(weatherRepositoryProvider);
  Position? location;

  try {
    location = await ref.watch(currentLocationProvider.future);
  } catch (_) {
    // 위치 호출 실패 시 기본 좌표 사용
    location = defaultPosition();
  }

  location ??= defaultPosition();

  // 캐시된 날씨 정보 확인
  final cached = await repository.getCachedWeather();
  if (cached != null) {
    return cached;
  }

  // 새로운 날씨 정보 가져오기
  return repository.getCurrentWeather(
    latitude: location.latitude,
    longitude: location.longitude,
  );
});

/// 날씨 업데이트 필요 여부 Provider
final isWeatherUpdateNeededProvider = FutureProvider<bool>((ref) async {
  final repository = ref.watch(weatherRepositoryProvider);
  return repository.isWeatherUpdateNeeded();
});

/// 날씨 관리 StateNotifier
class WeatherNotifier extends StateNotifier<AsyncValue<WeatherInfo>> {
  final WeatherRepository _repository;
  final Ref _ref;

  WeatherNotifier(this._repository, this._ref)
    : super(const AsyncValue.loading());

  /// 날씨 정보 새로고침
  Future<void> refreshWeather() async {
    state = const AsyncValue.loading();

    try {
      final location = await _ref.read(currentLocationProvider.future);
      if (location == null) {
        throw Exception('위치 정보를 가져올 수 없습니다');
      }

      final weather = await _repository.getCurrentWeather(
        latitude: location.latitude,
        longitude: location.longitude,
      );

      state = AsyncValue.data(weather);
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 캐시에서 날씨 정보 로드
  Future<void> loadCachedWeather() async {
    try {
      final cached = await _repository.getCachedWeather();
      if (cached != null) {
        state = AsyncValue.data(cached);
      } else {
        // 캐시가 없으면 새로 가져오기
        await refreshWeather();
      }
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }

  /// 날씨 캐시 삭제
  Future<void> clearCache() async {
    try {
      await _repository.clearWeatherCache();
    } catch (e, stack) {
      state = AsyncValue.error(e, stack);
    }
  }
}

/// WeatherNotifier Provider
final weatherNotifierProvider =
    StateNotifierProvider<WeatherNotifier, AsyncValue<WeatherInfo>>((ref) {
      final repository = ref.watch(weatherRepositoryProvider);
      return WeatherNotifier(repository, ref);
    });
