import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:universal_html/html.dart' as html;
import 'package:universal_html/js_util.dart';

class XAppSDKService {
  static final XAppSDKService _instance = XAppSDKService._internal();
  factory XAppSDKService() => _instance;
  XAppSDKService._internal();

  String? _token;
  Map<String, dynamic>? _user;
  bool _isReady = false;
  String? _error;

  String? get token => _token;
  Map<String, dynamic>? get user => _user;
  bool get isReady => _isReady;
  String? get error => _error;

  /// Initialize x-app-sdk service and get data from app host
  Future<void> initialize() async {
    if (!kIsWeb) return;

    try {
      // Wait longer for the JavaScript to initialize
      await Future.delayed(const Duration(milliseconds: 1000));
      
      // Check if AppHostData is available in window
      final appHostData = getProperty(html.window, 'AppHostData');
      if (appHostData != null) {
        final data = jsonDecode(appHostData.toString());
        _token = data['token'];
        _user = data['user'] != null ? Map<String, dynamic>.from(data['user']) : null;
        _isReady = data['isReady'] ?? false;
        _error = data['error'];
        
        print('✅ XAppSDK Service initialized:');
        print('   Token: ${_token != null ? '***${_token!.substring(_token!.length - 4)}' : 'null'}');
        print('   User: ${_user?.toString() ?? 'null'}');
        print('   Ready: $_isReady');
        if (_error != null) {
          print('   Error: $_error');
        }
      } else {
        print('❌ AppHostData not found in window, trying fallback...');
        await _tryFallbackMethod();
      }
    } catch (e) {
      print('❌ Error initializing XAppSDK Service: $e');
      await _tryFallbackMethod();
    }
  }

  /// Fallback method to get data from URL parameters or localStorage
  Future<void> _tryFallbackMethod() async {
    try {
      // Try to get from URL parameters first
      final uri = Uri.base;
      final token = uri.queryParameters['token'];
      final userStr = uri.queryParameters['user'];

      if (token != null && token.isNotEmpty) {
        _token = token;
        if (userStr != null && userStr.isNotEmpty) {
          try {
            _user = jsonDecode(userStr);
          } catch (e) {
            print('❌ Failed to parse user from URL: $e');
          }
        }
        _isReady = true;
        print('✅ Data loaded from URL parameters (fallback)');
        return;
      }

      // Try to get from localStorage
      final storedToken = html.window.localStorage['app_host_token'];
      final storedUser = html.window.localStorage['app_host_user'];

      if (storedToken != null && storedToken.isNotEmpty) {
        _token = storedToken;
        if (storedUser != null && storedUser.isNotEmpty) {
          try {
            _user = jsonDecode(storedUser);
          } catch (e) {
            print('❌ Failed to parse user from localStorage: $e');
          }
        }
        _isReady = true;
        print('✅ Data loaded from localStorage (fallback)');
      } else {
        print('❌ No data found in URL parameters or localStorage');
        _error = 'No data available from app host';
      }
    } catch (e) {
      print('❌ Error in fallback method: $e');
      _error = e.toString();
    }
  }

  /// Get token from app host
  String? getToken() {
    return _token;
  }

  /// Get user info from app host
  Map<String, dynamic>? getUser() {
    return _user;
  }

  /// Check if service is ready
  bool get isServiceReady => _isReady;

  /// Get error message if any
  String? getErrorMessage() {
    return _error;
  }

  /// Clear stored data
  void clearData() {
    _token = null;
    _user = null;
    _isReady = false;
    _error = null;
    
    if (kIsWeb) {
      try {
        html.window.localStorage.remove('app_host_token');
        html.window.localStorage.remove('app_host_user');
      } catch (e) {
        print('❌ Error clearing localStorage: $e');
      }
    }
  }

  /// Store data for future use
  void storeData(String token, Map<String, dynamic>? user) {
    _token = token;
    _user = user;
    _isReady = true;
    _error = null;
    
    if (kIsWeb) {
      try {
        html.window.localStorage['app_host_token'] = token;
        if (user != null) {
          html.window.localStorage['app_host_user'] = jsonEncode(user);
        }
      } catch (e) {
        print('❌ Error storing data: $e');
      }
    }
  }

  /// Listen for data updates from app host
  void listenForUpdates() {
    if (!kIsWeb) return;

    try {
      // Set up a periodic check for updates using js_util
      final intervalId = callMethod(html.window, 'setInterval', [
        allowInterop(() {
          final appHostData = getProperty(html.window, 'AppHostData');
          if (appHostData != null) {
            final data = jsonDecode(appHostData.toString());
            final newToken = data['token'];
            final newUser = data['user'];
            final newReady = data['isReady'] ?? false;
            final newError = data['error'];

            if (newReady && (newToken != _token || newUser != _user)) {
              _token = newToken;
              _user = newUser != null ? Map<String, dynamic>.from(newUser) : null;
              _isReady = newReady;
              _error = newError;
              print('🔄 XAppSDK data updated from app host');
            }
          }
        }),
        2000 // Check every 2 seconds
      ]);
      
      // Store interval ID for potential cleanup
      print('✅ Update listener set up with interval ID: $intervalId');
    } catch (e) {
      print('❌ Error setting up update listener: $e');
    }
  }

  /// Call x-app-sdk method directly from Super App
  Future<dynamic> callSDKMethod(String methodName, [List<dynamic>? args]) async {
    if (!kIsWeb) return null;

    try {
      // Check if method is available from Super App
      final methodExists = getProperty(html.window, methodName);
      if (methodExists == null) {
        print('❌ Method $methodName not available from Super App');
        return null;
      }

      // Call method directly using callMethod
      if (methodName == 'getToken') {
        return await promiseToFuture(callMethod(html.window, 'getToken', []));
      } else if (methodName == 'getInfo' && args != null && args.isNotEmpty) {
        return await promiseToFuture(callMethod(html.window, 'getInfo', [args[0]]));
      } else {
        print('❌ Unsupported method: $methodName');
        return null;
      }
    } catch (e) {
      print('❌ Error calling SDK method $methodName: $e');
      return null;
    }
  }

  /// Get user info by key from Super App
  Future<dynamic> getUserInfo(String key) async {
    return await callSDKMethod('getInfo', [key]);
  }

  /// Get token from Super App
  Future<String?> getTokenAsync() async {
    return await callSDKMethod('getToken');
  }

  /// Check if x-app-sdk is available from Super App
  bool isSDKAvailable() {
    if (!kIsWeb) return false;
    
    try {
      final getToken = getProperty(html.window, 'getToken');
      final getInfo = getProperty(html.window, 'getInfo');
      return getToken != null && getInfo != null;
    } catch (e) {
      return false;
    }
  }

  /// Close app and return to Super App
  void closeApp([Map<String, dynamic>? data]) {
    if (!kIsWeb) return;

    try {
      print('🚪 Closing app and returning to Super App...');
      if (data != null) {
        print('📤 Data to return: $data');
      }

      // Call the JavaScript closeApp function
      callMethod(html.window, 'closeApp', [data]);
      print('✅ closeApp called successfully');
    } catch (e) {
      print('❌ Error calling closeApp: $e');
      // Fallback: try to close the window
      try {
        html.window.close();
      } catch (fallbackError) {
        print('❌ Fallback close also failed: $fallbackError');
      }
    }
  }
}
