import 'package:flutter/foundation.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';

/// OneSignal service for managing push notifications and external user ID.
///
/// This service handles:
/// - Initializing OneSignal SDK
/// - Setting external user ID after login (using phone number)
/// - Restoring external user ID on app startup
/// - Clearing external user ID on logout
///
/// Usage:
/// ```dart
/// // Initialize in main.dart
/// await OneSignalService.init(appId: 'your-app-id');
///
/// // After successful login
/// await OneSignalService.login(phoneNumber);
///
/// // On logout
/// await OneSignalService.logout();
/// ```
class OneSignalService {
  OneSignalService._();

  /// OneSignal App ID - Replace with your actual App ID from OneSignal dashboard
  static const String _defaultAppId = '778ca22d-c719-4ec8-86cb-a6b911166066';

  /// Initialize OneSignal SDK
  ///
  /// Must be called before using any other OneSignal methods.
  /// Sets up push subscription observers and requests notification permission.
  ///
  /// [appId] - Optional App ID override (uses default if not provided)
  /// [requestPermission] - Whether to request notification permission (default: true)
  static Future<void> init({
    String? appId,
    bool requestPermission = true,
  }) async {
    try {
      // Set debug log level (verbose in debug, none in release)
      OneSignal.Debug.setLogLevel(kDebugMode ? OSLogLevel.verbose : OSLogLevel.none);

      // Initialize with App ID
      OneSignal.initialize(appId ?? _defaultAppId);
      debugPrint('🔔 OneSignal initialized');

      // Add push subscription observer to track subscription state changes
      OneSignal.User.pushSubscription.addObserver((state) {
        debugPrint('🔔 Push subscription state changed:');
        debugPrint('  Previous - optedIn: ${state.previous.optedIn}, id: ${state.previous.id}');
        debugPrint('  Current - optedIn: ${state.current.optedIn}, id: ${state.current.id}');
        debugPrint('  Subscription ID: ${state.current.id}');
        debugPrint('  Push Token: ${state.current.token}');

        if (state.current.id != null) {
          debugPrint('🔔 ✅ Device successfully subscribed!');
        }
      });

      // Add notification permission observer
      OneSignal.Notifications.addPermissionObserver((isGranted) {
        debugPrint('🔔 Notification permission changed: $isGranted');
      });

      // Request permission if enabled
      if (requestPermission) {
        final accepted = await OneSignal.Notifications.requestPermission(true);
        debugPrint('🔔 Permission request result: $accepted');
      }

      // Give OneSignal SDK time to complete initialization and server registration
      await Future<void>.delayed(const Duration(seconds: 2));

      // Log current subscription status
      _logSubscriptionStatus();
    } catch (e) {
      debugPrint('🔔 OneSignal error: Failed to initialize - $e');
    }
  }

  /// Log current subscription status for debugging
  static void _logSubscriptionStatus() {
    final optedIn = OneSignal.User.pushSubscription.optedIn;
    final id = OneSignal.User.pushSubscription.id;
    final token = OneSignal.User.pushSubscription.token;

    debugPrint('🔔 Current subscription status:');
    debugPrint('  Opted In: $optedIn');
    debugPrint('  Subscription ID: $id');
    debugPrint('  Push Token: $token');

    if (id == null) {
      debugPrint('🔔 ⚠️  Subscription ID is null - check device connectivity and OneSignal app ID');
    }
  }

  /// Login user to OneSignal by setting external user ID.
  ///
  /// This associates the device with the user's phone number,
  /// allowing targeted push notifications to specific users.
  ///
  /// [phoneNumber] - The user's phone number (used as external ID)
  static Future<void> login(String phoneNumber) async {
    try {
      // Set external user ID for targeting
      await OneSignal.login(phoneNumber);
      debugPrint('🔔 OneSignal: login - external_id set to $phoneNumber');
    } catch (e) {
      debugPrint('🔔 OneSignal error: Failed to set external user ID - $e');
    }
  }

  /// Logout user from OneSignal by removing external user ID.
  ///
  /// This disassociates the device from the user,
  /// so notifications won't be sent to this specific user anymore.
  static Future<void> logout() async {
    try {
      await OneSignal.logout();
      debugPrint('🔔 OneSignal: logout - external_id cleared');
    } catch (e) {
      debugPrint('🔔 OneSignal error: Failed to clear external user ID - $e');
    }
  }

  /// Add a tag to the user for segmentation.
  ///
  /// Tags can be used to segment users for targeted notifications.
  /// Example: tier = "diamond", role = "contractor"
  static Future<void> setTag(String key, String value) async {
    try {
      await OneSignal.User.addTagWithKey(key, value);
      debugPrint('🔔 OneSignal: tag set - $key: $value');
    } catch (e) {
      debugPrint('🔔 OneSignal error: Failed to set tag - $e');
    }
  }

  /// Add multiple tags at once.
  static Future<void> setTags(Map<String, String> tags) async {
    try {
      await OneSignal.User.addTags(tags);
      debugPrint('🔔 OneSignal: tags set - $tags');
    } catch (e) {
      debugPrint('🔔 OneSignal error: Failed to set tags - $e');
    }
  }

  /// Remove a tag from the user.
  static Future<void> removeTag(String key) async {
    try {
      await OneSignal.User.removeTag(key);
      debugPrint('🔔 OneSignal: tag removed - $key');
    } catch (e) {
      debugPrint('🔔 OneSignal error: Failed to remove tag - $e');
    }
  }

  /// Get the OneSignal subscription ID (player ID).
  ///
  /// This is the device-specific ID used by OneSignal.
  static String? get subscriptionId => OneSignal.User.pushSubscription.id;

  /// Check if push notifications are enabled.
  static bool get isPushEnabled =>
      OneSignal.User.pushSubscription.optedIn ?? false;
}
