import 'dart:convert';
import '../constants/api_constants.dart';
import 'http_service.dart';
import 'auth_service.dart';
import 'cache_service.dart';

class UserService {
  static bool _pollingStarted = false;
  /// Get current user with caching - returns cached data if available and fresh
  static Future<Map<String, dynamic>> getCurrentUser({bool forceRefresh = false}) async {
    // Return cached data if available and not forcing refresh
    if (!forceRefresh) {
      final cached = CacheService.getCached<Map<String, dynamic>>(CacheService.userProfileKey);
      if (cached != null && !CacheService.isCacheExpired(CacheService.userProfileKey, CacheService.userCacheDuration)) {
        return {
          'success': true,
          'message': 'Loaded from cache',
          'data': cached,
        };
      }
      
      // Return stale data while fetching fresh data in background
      final stale = CacheService.getCachedStale<Map<String, dynamic>>(CacheService.userProfileKey);
      if (stale != null && !forceRefresh) {
        // Trigger background refresh
        _fetchAndCacheUser();
        return {
          'success': true,
          'message': 'Loaded from cache (refreshing in background)',
          'data': stale,
        };
      }
      
      // Also check AuthService cache for backward compatibility
      final authCachedData = await AuthService.getCachedUserData();
      if (authCachedData != null) {
        // Update our cache with auth service data
        CacheService.setCached(CacheService.userProfileKey, authCachedData);
        return {'success': true, 'data': authCachedData};
      }
    }

    // Fetch fresh data
    return await _fetchAndCacheUser();
  }

  static Future<Map<String, dynamic>> _fetchAndCacheUser([bool fromPolling = false]) async {
    try {
      final response = await HttpService.get(ApiConstants.getUserEndpoint);

      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        
        // Only cache when not called from polling to prevent conflicts
        if (!fromPolling) {
          CacheService.setCached(CacheService.userProfileKey, data);
        }
        
        // Also save to AuthService for backward compatibility
        await AuthService.saveUserData(data);
        
        return {
          'success': true, 
          'data': data,
          'message': '',
        };
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
          'data': null,
        };
      } else {
        return {
          'success': false,
          'message': 'Server error (${response.statusCode})',
          'data': null,
        };
      }
    } catch (e) {
      print('Error fetching user: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
        'data': null,
      };
    }
  }

  /// Start background polling for user profile
  static void startPolling() {
    _pollingStarted = true;
    CacheService.startPolling(
      CacheService.userProfileKey,
      () => _fetchAndCacheUser(true), // Mark as from polling
      CacheService.userPollingInterval,
      CacheService.userCacheDuration,
    );
  }

  /// Stop background polling for user profile
  static void stopPolling() {
    CacheService.stopPolling(CacheService.userProfileKey);
    _pollingStarted = false;
  }

  /// Get user profile stream for real-time updates
  static Stream<Map<String, dynamic>> getUserStream() {
    return CacheService.getStream<Map<String, dynamic>>(CacheService.userProfileKey);
  }

  /// Force notify stream with current cached data (useful for initial stream setup)
  static void notifyStreamWithCurrentData() {
    final cached = CacheService.getCachedStale<Map<String, dynamic>>(
      CacheService.userProfileKey,
    );
    if (cached != null) {
      // Re-notify the stream with current data
      CacheService.notifyStreamListeners<Map<String, dynamic>>(
        CacheService.userProfileKey,
        cached,
      );
    }
  }

  /// Check if polling is active
  static bool get isPollingActive => _pollingStarted;

  /// Invalidate user cache (useful after updating profile)
  static void invalidateCache() {
    CacheService.clearCache(CacheService.userProfileKey);
  }

  static Future<Map<String, dynamic>> updateFCMToken(String fcmToken) async {
    try {
      final response = await HttpService.post(ApiConstants.updateUserEndpoint, {
        'fcmToken': fcmToken,
      });

      if (response.statusCode == 200) {
        return {'success': true};
      } else if (response.statusCode == 401) {
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
        };
      } else if (response.statusCode == 403) {
        return {
          'success': false,
          'message': 'Access denied. Invalid credentials.',
        };
      } else {
        return {
          'success': false,
          'message': 'Server error (${response.statusCode})',
        };
      }
    } catch (e) {
      print('Error updating FCM token: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }

  static Future<Map<String, dynamic>> updateUser({
    String? displayName,
    String? username,
    String? avatar,
    List<String>? subscriptions,
  }) async {
    try {
      final Map<String, dynamic> updateData = {};
      if (displayName != null) updateData['displayName'] = displayName;
      if (username != null) updateData['username'] = username;
      if (avatar != null) updateData['avatar'] = avatar;
      if (subscriptions != null) updateData['subscriptions'] = subscriptions;

      final response = await HttpService.post(ApiConstants.updateUserEndpoint, updateData);

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        
        if (responseData['status'] == true) {
          // Update cache with new user data
          CacheService.setCached(CacheService.userProfileKey, responseData['data']);
          // Also save to AuthService for backward compatibility
          await AuthService.saveUserData(responseData['data']);
          
          return {
            'success': true,
            'message': responseData['message'] ?? 'Profile updated successfully',
            'data': responseData['data'],
          };
        } else {
          return {
            'success': false,
            'message': responseData['message'] ?? 'Failed to update profile',
          };
        }
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
        };
      } else {
        final responseData = jsonDecode(response.body);
        return {
          'success': false,
          'message': responseData['message'] ?? 'Server error (${response.statusCode})',
        };
      }
    } catch (e) {
      print('Error updating user: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }

  static Future<Map<String, dynamic>> createUser({
    required String email,
    required String password,
    required String displayName,
  }) async {
    try {
      final response = await HttpService.post('/admin/createUser', {
        'email': email,
        'password': password,
        'displayName': displayName,
      });

      final responseData = jsonDecode(response.body);

      if (response.statusCode == 200 || response.statusCode == 201) {
        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? 'User created successfully',
          'data': responseData['data'],
        };
      } else {
        return {
          'success': false,
          'message': responseData['message'] ?? 'Failed to create user',
        };
      }
    } catch (e) {
      print('Error creating user: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }

  static Future<Map<String, dynamic>> updateUserSubscriptions(List<String> subscriptions) async {
    return updateUser(subscriptions: subscriptions);
  }
}
