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

class InvitationsService {
  static bool _pollingStarted = false;

  /// Get all invitations with caching - returns cached data if available and fresh
  static Future<Map<String, dynamic>> getAllInvitations({
    bool forceRefresh = false,
  }) async {
    // Return cached data if available and not forcing refresh
    if (!forceRefresh) {
      final cached = CacheService.getCached<InvitationsData>(
        CacheService.invitationsAllKey,
      );
      if (cached != null &&
          !CacheService.isCacheExpired(
            CacheService.invitationsAllKey,
            CacheService.invitationsCacheDuration,
          )) {
        return {
          'success': true,
          'message': 'Loaded from cache',
          'invitations': cached,
        };
      }

      // Return stale data while fetching fresh data in background
      final stale = CacheService.getCachedStale<InvitationsData>(
        CacheService.invitationsAllKey,
      );
      if (stale != null && !forceRefresh) {
        // Trigger background refresh
        _fetchAndCacheInvitations();
        return {
          'success': true,
          'message': 'Loaded from cache (refreshing in background)',
          'invitations': stale,
        };
      }
    }

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

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

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        final invitationsResponse = InvitationsResponse.fromJson(responseData);

        if (invitationsResponse.status) {
          final invitationsData = invitationsResponse.data;

          // Only cache when not called from polling to prevent conflicts
          if (!fromPolling) {
            CacheService.setCached(
              CacheService.invitationsAllKey,
              invitationsData,
            );
          }

          return {
            'success': true,
            'invitations': invitationsData,
            'message': invitationsResponse.message ?? '',
          };
        } else {
          return {
            'success': false,
            'message':
                invitationsResponse.message ?? 'Failed to fetch invitations',
            'invitations': InvitationsData(
              created: [],
              accepted: [],
              available: [],
            ),
          };
        }
      } else if (response.statusCode == 401 || response.statusCode == 403) {
        await AuthService.handleAuthenticationError();
        return {
          'success': false,
          'message': 'Session expired. Please login again.',
          'invitations': InvitationsData(
            created: [],
            accepted: [],
            available: [],
          ),
        };
      } else {
        return {
          'success': false,
          'message': 'Server error (${response.statusCode})',
          'invitations': InvitationsData(
            created: [],
            accepted: [],
            available: [],
          ),
        };
      }
    } catch (e) {
      print('Error fetching invitations: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
        'invitations': InvitationsData(
          created: [],
          accepted: [],
          available: [],
        ),
      };
    }
  }

  /// Start background polling for invitations
  static void startPolling() {
    _pollingStarted = true;
    CacheService.startPolling(
      CacheService.invitationsAllKey,
      () => _fetchAndCacheInvitations(true), // Mark as from polling
      CacheService.invitationsPollingInterval,
      CacheService.invitationsCacheDuration,
    );
  }

  /// Stop background polling for invitations
  static void stopPolling() {
    CacheService.stopPolling(CacheService.invitationsAllKey);
    _pollingStarted = false;
  }

  /// Get invitations stream for real-time updates
  static Stream<InvitationsData> getInvitationsStream() {
    return CacheService.getStream<InvitationsData>(
      CacheService.invitationsAllKey,
    );
  }

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

  /// Invalidate invitations cache (useful after creating/updating invitations)
  static void invalidateCache() {
    CacheService.clearCache(CacheService.invitationsAllKey);
  }

  static Future<Map<String, dynamic>> acceptInvitation(int invitationId) async {
    try {
      final response = await HttpService.post(
        ApiConstants.acceptInvitationEndpoint,
        {'id': invitationId},
      );

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        // Invalidate invitations cache since invitation status changed
        invalidateCache();
        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? 'Request completed',
        };
      } 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 accepting invitation: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }

  static Future<Map<String, dynamic>> createInvitation(
    Map<String, dynamic> invitationData,
  ) async {
    try {
      final response = await HttpService.post(
        ApiConstants.createInvitationEndpoint,
        invitationData,
      );

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        if (responseData['status'] == true) {
          // Invalidate invitations cache since new invitation was created
          invalidateCache();
          return {
            'success': true,
            'data': responseData['data'],
            'message': responseData['message'],
          };
        } else {
          return {
            'success': false,
            'message': responseData['message'] ?? 'Failed to create invitation',
          };
        }
      } 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 creating invitation: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }

  static Future<Map<String, dynamic>> getInvitationDetails(
    int invitationId,
  ) async {
    try {
      final response = await HttpService.get(
        '${ApiConstants.invitationsEndpoint}/get?id=$invitationId',
      );

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        if (responseData['status'] == true) {
          final invitationDetails = InvitationDetails.fromJson(
            responseData['data'],
          );
          return {'success': true, 'data': invitationDetails};
        } else {
          return {
            'success': false,
            'message':
                responseData['message'] ?? 'Failed to get invitation details',
          };
        }
      } 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 getting invitation details: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }

  static Future<Map<String, dynamic>> cancelInvitation(int invitationId) async {
    try {
      final response = await HttpService.post(
        '${ApiConstants.invitationsEndpoint}/cancel',
        {'id': invitationId},
      );

      if (response.statusCode == 200) {
        final responseData = jsonDecode(response.body);
        return {
          'success': responseData['status'] ?? false,
          'message': responseData['message'] ?? 'Request completed',
        };
      } 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 canceling invitation: $e');
      return {
        'success': false,
        'message': 'Network error. Please check your connection.',
      };
    }
  }
}
