import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/networking/restful_api_viewmodel.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/shared/router_gage.dart';
import '../../model/auth/login_token_response_model.dart';
import '../../model/auth/profile_response_model.dart';
import 'models/update_response_model.dart';
import '../../preference/data_preference.dart';
import '../../preference/point/point_manager.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../web/web_helper.dart';
import '../popup_manager/popup_manager_viewmodel.dart';

class SplashScreenViewModel extends RestfulApiViewModel {
  void Function(UpdateResponseModel? data)? checkUpdateResponse;
  var _updateLink = '';
  static const Duration _networkTimeout = Duration(seconds: 20);
  static const Duration _sdkTimeout = Duration(seconds: 20);

  Future<void> checkUpdateApp() async {
    try {
      final response = await client.checkUpdateApp().timeout(_networkTimeout);
      _updateLink = response.data?.updateRequest?.firstOrNull?.updateLink.orEmpty ?? '';
      checkUpdateResponse?.call(response.data);
    } on Object catch (e) {
      debugPrint('⚠️ SplashScreen - checkUpdateApp failed: $e');
      checkUpdateResponse?.call(null);
    }
  }

  Future<void> openLink() async {
    if (_updateLink.isEmpty) return;
    final Uri url = Uri.parse(_updateLink);
    if (await canLaunchUrl(url)) {
      await launchUrl(url);
    }
  }

  Future<void> makeDataFollowInitApp() async {
    try {
      if (DataPreference.instance.logged) {
        await _loadProfileAndNavigate();
        return;
      }

      final token = await _getTokenFromSDK();
      if (token.orEmpty.isEmpty) {
        directionWhenTokenInvalid();
        return;
      }

      await DataPreference.instance.saveLoginToken(LoginTokenResponseModel(accessToken: token));
      await _loadProfileAndNavigate();
    } on Object catch (e) {
      debugPrint('❌ SplashScreen - makeDataFollowInitApp error: $e');
      DataPreference.instance.clearLoginToken();
      directionWhenTokenInvalid();
    }
  }

  /// Get token from x-app-sdk (web only)
  Future<String?> _getTokenFromSDK() async {
    if (!kIsWeb) {
      debugPrint('🔍 SplashScreen - Not on web, skipping SDK token retrieval');
      return null;
    }
    try {
      debugPrint('🔍 SplashScreen - Attempting to get token from x-app-sdk...');
      await webInitializeXAppSDK().timeout(_sdkTimeout);
      if (!webIsSDKInitialized()) {
        debugPrint('⚠️ SplashScreen - SDK not initialized, skipping');
        return null;
      }
      // Get token from SDK
      final token = await webGetToken().timeout(_sdkTimeout);
      if (token != null && token.isNotEmpty) {
        debugPrint('✅ SplashScreen - Token retrieved from x-app-sdk: ${token.substring(0, 8)}...');
        return token;
      } else {
        final error = webGetLastError();
        debugPrint('❌ SplashScreen - Failed to get token from SDK: $error');
        return null;
      }
    } catch (e) {
      debugPrint('❌ SplashScreen - Error getting token from SDK: $e');
      return null;
    }
  }

  Future<void> _loadProfileAndNavigate() async {
    final profile = await _fetchUserProfile();
    if (profile == null) {
      DataPreference.instance.clearLoginToken();
      directionWhenTokenInvalid();
      return;
    }
    await _prepareInitialData(profile);
    _goToMain();
  }

  Future<void> directionWhenTokenInvalid() async {
    if (Get.currentRoute == onboardingScreen) return;
    if (kIsWeb) {
      print('❌ No token found on web, closing app');
      final closeSuccess = await webCloseApp({
        'message': 'No token found, cannot proceed',
        'timestamp': DateTime.now().millisecondsSinceEpoch,
      });
      if (closeSuccess) return;
    }
    final phone = DataPreference.instance.phoneNumberUsedForLoginScreen;
    final displayName = DataPreference.instance.displayName;
    if (phone.isEmpty) {
      Get.offAllNamed(onboardingScreen);
    } else {
      Get.offAllNamed(loginScreen, arguments: {"phone": phone, 'fullName': displayName});
    }
  }

  Future<ProfileResponseModel?> _fetchUserProfile() async {
    try {
      final response = await client.getUserProfile().timeout(_networkTimeout);
      if (response.isSuccess) {
        return response.data;
      }
      debugPrint('⚠️ SplashScreen - getUserProfile failed: ${response.errorMessage ?? response.message}');
    } on TimeoutException catch (_) {
      debugPrint('⚠️ SplashScreen - getUserProfile timeout');
    } catch (e) {
      debugPrint('⚠️ SplashScreen - getUserProfile error: $e');
    }
    return null;
  }

  Future<void> _prepareInitialData(ProfileResponseModel profile) async {
    await _runSafely(() => DataPreference.instance.saveUserProfile(profile), 'cache user profile');
    await _runSafely(() => UserPointManager().fetchUserPoint(), 'fetch user point');
    await _runSafely(() => PopupManagerViewModel.instance.ensureLoaded(), 'preload popups');
  }

  Future<void> _runSafely(Future<void> Function() task, String label) async {
    try {
      await task().timeout(_networkTimeout);
    } on TimeoutException catch (_) {
      debugPrint('⚠️ SplashScreen - $label timeout');
    } catch (e) {
      debugPrint('⚠️ SplashScreen - $label failed: $e');
    }
  }

  void _goToMain() {
    if (Get.currentRoute == mainScreen) return;
    if (Get.currentRoute == onboardingScreen) {
      Get.offNamed(mainScreen);
    } else {
      Get.offAllNamed(mainScreen);
    }
  }
}
