import 'package:real_estate_mobile/core/network/api_client.dart';

class _CachedUrl {
  final String url;
  final DateTime cachedAt;
  _CachedUrl(this.url) : cachedAt = DateTime.now();

  /// Presigned URLs typically expire in 1 hour; refresh after 45 minutes.
  bool get isExpired =>
      DateTime.now().difference(cachedAt).inMinutes >= 45;
}

/// Resolves S3 keys to presigned download URLs via the backend API.
/// Caches results in memory with expiry to handle presigned URL expiration.
class ImageUrlResolver {
  ImageUrlResolver._();
  static final ImageUrlResolver instance = ImageUrlResolver._();

  final Map<String, _CachedUrl> _cache = {};
  final Map<String, Future<String?>> _pending = {};

  /// Returns a direct image URL.
  /// - If [imageUrl] is already an http(s) URL, returns it as-is.
  /// - If it's an S3 key, fetches a presigned download URL from the backend.
  Future<String?> resolve(String? imageUrl) async {
    if (imageUrl == null || imageUrl.isEmpty) return null;
    if (imageUrl.startsWith('http://') || imageUrl.startsWith('https://')) {
      return imageUrl;
    }

    // Check cache — only use if not expired
    final cached = _cache[imageUrl];
    if (cached != null && !cached.isExpired) return cached.url;

    // Deduplicate in-flight requests for the same key
    if (_pending.containsKey(imageUrl)) return _pending[imageUrl];

    final future = _fetchPresignedUrl(imageUrl);
    _pending[imageUrl] = future;

    try {
      final result = await future;
      if (result != null) _cache[imageUrl] = _CachedUrl(result);
      return result;
    } finally {
      _pending.remove(imageUrl);
    }
  }

  Future<String?> _fetchPresignedUrl(String key) async {
    try {
      final response = await ApiClient.instance.dio.get(
        '/upload/presigned-download-url',
        queryParameters: {'key': key},
      );
      final data = response.data;
      // Backend wraps: { success: true, data: { url: "..." } }
      if (data is Map<String, dynamic>) {
        final payload = data['data'];
        if (payload is Map<String, dynamic>) {
          return payload['url'] as String?;
        }
        // In case response isn't wrapped (direct controller return)
        return data['url'] as String?;
      }
      return null;
    } catch (_) {
      return null;
    }
  }

  void clearCache() => _cache.clear();

  /// Evict a single key from the in-memory cache so the next resolve
  /// fetches a fresh presigned URL.
  void evict(String? key) {
    if (key != null) _cache.remove(key);
  }
}
