import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:tugas_akhir_supabase/core/constants/app_constants.dart';
import 'package:tugas_akhir_supabase/di/service_locator.dart';
import 'package:tugas_akhir_supabase/core/routes/app_routes.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:tugas_akhir_supabase/services/session_manager.dart';
import 'package:tugas_akhir_supabase/services/user_presence_service.dart';
import 'package:tugas_akhir_supabase/widgets/session_expired_dialog.dart';
import 'package:get_it/get_it.dart';
import 'package:tugas_akhir_supabase/widgets/session_guard_wrapper.dart';
import 'package:tugas_akhir_supabase/screens/intro/intro_page_screen.dart'
    as intro;

// Tambahkan listener untuk hot reload
bool _hasDoneHotReloadSetup = false;

// Global navigator key for accessing navigation from anywhere
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

// Fungsi isolate terpisah untuk inisialisasi Supabase
Future<void> _initializeSupabase() async {
  try {
    await Supabase.initialize(
      url: AppConstants.supabaseUrl,
      anonKey: AppConstants.supabaseAnonKey,
      debug: false,
    );
    debugPrint('Supabase initialized successfully');
  } catch (e) {
    debugPrint('Error initializing Supabase: $e');
    rethrow;
  }
}

void main() async {
  // Langsung memulai aplikasi utama
  try {
    // Initialize Flutter binding
    WidgetsFlutterBinding.ensureInitialized();

    // Tambahkan penanganan error global
    PlatformDispatcher.instance.onError = (error, stack) {
      debugPrint('Global error handler: $error');
      debugPrint('Stack trace: $stack');
      // Return true to prevent the error from being reported to the framework
      return true;
    };

    // Tambahkan dukungan untuk hot reload
    if (!_hasDoneHotReloadSetup) {
      _hasDoneHotReloadSetup = true;

      // Set debug flags
      debugPrint('======= Setting up hot reload support =======');

      // Pastikan semua yang memblokir hot reload dibersihkan
      final binding = WidgetsFlutterBinding.ensureInitialized();
      binding.addPostFrameCallback((_) {
        // Execute after first frame is rendered
        debugPrint(
          '======= First frame rendered, hot reload should work =======',
        );
      });
    }

    // Debug log untuk pelacakan splash screen
    debugPrint('======= App Start: Loading TaniSMART application =======');

    // Set orientation to portrait
    await SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);

    // Set up error handlers
    FlutterError.onError = (FlutterErrorDetails details) {
      debugPrint('Flutter error: ${details.exception}');
    };

    // Initialize date formatting
    await initializeDateFormatting('id_ID');
    await initializeDateFormatting('en_US');

    // Initialize Supabase dengan timeout
    try {
      // Gunakan timeout untuk mencegah blocking terlalu lama
      await _initializeSupabase().timeout(
        const Duration(seconds: 5),
        onTimeout: () {
          debugPrint('Supabase initialization timed out, continuing startup');
          throw TimeoutException('Supabase initialization timed out');
        },
      );
    } catch (e) {
      // Lanjutkan meskipun ada error, akan ditangani nanti
      debugPrint('Continuing after Supabase initialization issue: $e');
    }

    // Initialize service locator dengan timeout
    try {
      await initServiceLocator().timeout(
        const Duration(seconds: 3),
        onTimeout: () {
          debugPrint('Service locator initialization timed out, continuing');
          throw TimeoutException('Service locator initialization timed out');
        },
      );
    } catch (e) {
      debugPrint('Continuing after service locator issue: $e');
    }

    // Initialize session management dengan timeout
    try {
      await SessionManager.initializeSession().timeout(
        const Duration(seconds: 3),
        onTimeout: () {
          debugPrint('Session initialization timed out, continuing');
          throw TimeoutException('Session initialization timed out');
        },
      );

      // Initialize user presence service if user is logged in
      if (Supabase.instance.client.auth.currentUser != null) {
        try {
          if (GetIt.instance.isRegistered<UserPresenceService>()) {
            await GetIt.instance<UserPresenceService>().initialize();
            debugPrint('User presence service initialized');
          }
        } catch (e) {
          debugPrint('Error initializing user presence service: $e');
        }
      }
    } catch (e) {
      debugPrint('Continuing after session initialization issue: $e');
    }

    // Debug log sebelum menjalankan aplikasi
    debugPrint(
      '======= App initialized: Running TaniSMART application =======',
    );

    // Run the app
    runApp(const RealApp());
  } catch (e, stack) {
    debugPrint('Error starting full app: $e\n$stack');

    // Show error screen
    runApp(
      MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: const Text('TaniSMART Error'),
            backgroundColor: Colors.red,
          ),
          body: Center(
            child: Padding(
              padding: const EdgeInsets.all(20.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Icon(Icons.error_outline, color: Colors.red, size: 48),
                  const SizedBox(height: 16),
                  const Text(
                    'Aplikasi tidak dapat dimulai',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 8),
                  Text(
                    'Error: ${e.toString()}',
                    style: const TextStyle(color: Colors.red),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 24),
                  ElevatedButton(
                    onPressed: () {
                      main();
                    },
                    child: const Text('Coba Lagi'),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class RealApp extends StatefulWidget {
  const RealApp({super.key});

  @override
  State<RealApp> createState() => _RealAppState();
}

class _RealAppState extends State<RealApp> with WidgetsBindingObserver {
  bool _showingSessionExpiredDialog = false;
  bool _isInitialLaunch = true; // Flag untuk menandai initial launch
  Timer? _initialLaunchTimer;
  StreamSubscription? _sessionSubscription;
  Timer? _sessionCheckTimer; // Timer untuk memeriksa sesi secara berkala
  bool _hasSetupSessionMonitoring =
      false; // Flag baru untuk menandai setup monitoring

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);

    // Penundaan yang lebih lama untuk pemasangan listener agar aplikasi bisa dimuat sepenuhnya
    Future.delayed(Duration(seconds: 7), () {
      if (!mounted) return;

      // Hanya setup jika aplikasi masih berjalan dan belum setup
      if (!_hasSetupSessionMonitoring) {
        _setupSessionMonitoring();
      }
    });

    // Delay pemeriksaan session sampai aplikasi benar-benar siap
    // Beri waktu splash screen menyelesaikan animasinya dan navigasi selesai
    _initialLaunchTimer = Timer(Duration(seconds: 10), () {
      if (mounted) {
        setState(() {
          _isInitialLaunch =
              false; // Reset flag setelah initial launch benar-benar selesai
          debugPrint('App: Initial launch phase completed');
        });

        // Hanya setup jika aplikasi masih berjalan dan belum setup
        if (!_hasSetupSessionMonitoring) {
          _setupSessionMonitoring();
        }
      }
    });
  }

  // Metode terpisah untuk setup monitoring sesi
  void _setupSessionMonitoring() {
    if (_hasSetupSessionMonitoring) return; // Hindari setup duplikat
    _hasSetupSessionMonitoring = true;

    debugPrint('App: Setting up session expiration listener');

    _sessionSubscription = SessionManager.sessionExpiredStream.listen((
      expired,
    ) {
      debugPrint('App: Session expired event received: $expired');
      final currentUser = Supabase.instance.client.auth.currentUser;
      if (expired && !_showingSessionExpiredDialog && currentUser != null) {
        debugPrint('App: Showing session expired dialog from stream');
        _showSessionExpiredDialog();
      }
    });

    // Mulai pemeriksaan sesi yang lebih agresif (DISABLED)
    void startAggressiveSessionChecking() {
      debugPrint('App: Session monitoring DISABLED for permissive mode');

      // Cancel any existing timer
      _sessionCheckTimer?.cancel();

      // No timer setup - completely disabled
      debugPrint('App: No periodic session checks will run');
    }
  }

  // Check session validity on startup and periodically (DISABLED)
  Future<void> _checkSessionValidity() async {
    // Session checking DISABLED for permissive mode
    debugPrint('App: Session checking DISABLED for permissive mode');
    return;
  }

  @override
  void dispose() {
    _initialLaunchTimer?.cancel();
    _sessionSubscription?.cancel();
    _sessionCheckTimer?.cancel();
    WidgetsBinding.instance.removeObserver(this);
    SessionManager.dispose();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    debugPrint('App lifecycle state changed to: $state');

    switch (state) {
      case AppLifecycleState.paused:
      case AppLifecycleState.inactive:
      case AppLifecycleState.detached:
        // App went to background
        debugPrint('App: Going to background, calling onAppBackground');
        SessionManager.onAppBackground();
        break;
      case AppLifecycleState.resumed:
        // App came to foreground
        debugPrint('App: Coming to foreground, calling onAppForeground');
        SessionManager.onAppForeground().then((_) {
          debugPrint(
            'App: After foreground transition, expired = ${SessionManager.isExpired}',
          );

          // Periksa apakah pengguna sudah login terlebih dahulu
          final currentUser = Supabase.instance.client.auth.currentUser;
          if (currentUser == null) {
            debugPrint(
              'App: No authenticated user after foreground, skipping session check',
            );
            return;
          }

          if (SessionManager.isExpired && !_showingSessionExpiredDialog) {
            debugPrint('App: Session expired after coming to foreground');
            _showSessionExpiredDialog();
          } else {
            // Periksa sesi secara manual untuk memastikan
            _checkSessionValidity();
          }
        });
        break;
      default:
        break;
    }
  }

  void _showSessionExpiredDialog() {
    // Session expired dialog DISABLED for permissive mode
    debugPrint('App: Session expired dialog DISABLED for permissive mode');
    return;
  }

  // Reset expired dialog state saat login/logout
  void _resetExpiredDialogState() {
    _showingSessionExpiredDialog = false;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TaniSMART',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
        primaryColor: const Color(0xFF056839),
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF056839),
          brightness: Brightness.light,
        ),
        useMaterial3: true,
        fontFamily: 'Poppins',
        appBarTheme: const AppBarTheme(
          backgroundColor: Color(0xFF056839),
          foregroundColor: Colors.white,
          elevation: 0,
          centerTitle: true,
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            backgroundColor: const Color(0xFF056839),
            foregroundColor: Colors.white,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
          ),
        ),
        inputDecorationTheme: InputDecorationTheme(
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(color: Color(0xFF056839), width: 2),
          ),
        ),
      ),
      home: const intro.AnimatedIntroScreen(),
      routes: Map.from(AppRoutes.routes)..remove('/'),
      // Add navigation observer to clear SnackBars when navigating
      navigatorObservers: [
        _SnackBarClearingNavigatorObserver(),
        _UserInteractionObserver(),
      ],
      // Add router to intercept navigation when session is expired
      builder: (context, child) {
        // Force login screen if session is expired
        if (SessionManager.isExpired &&
            child != null &&
            !_isInitialLaunch &&
            Supabase.instance.client.auth.currentUser != null) {
          debugPrint('App: Session expired, forcing login screen');

          // Show session expired dialog if not already showing
          if (!_showingSessionExpiredDialog) {
            // Use a post-frame callback to avoid build phase issues
            WidgetsBinding.instance.addPostFrameCallback((_) {
              _showSessionExpiredDialog();
            });
          }

          // Return a restricted UI that prevents interaction
          return Material(
            child: Stack(
              children: [
                // Blur the background content
                Opacity(opacity: 0.3, child: child),
                // Show a loading indicator or message
                if (!_showingSessionExpiredDialog)
                  const Center(child: CircularProgressIndicator()),
              ],
            ),
          );
        }

        // Normal app flow
        return GestureDetector(
          onTap: () => _updateUserInteraction(),
          onPanDown: (_) => _updateUserInteraction(),
          onScaleStart: (_) => _updateUserInteraction(),
          behavior: HitTestBehavior.translucent,
          child: child!,
        );
      },
    );
  }

  // Method untuk memperbarui timestamp interaksi pengguna
  void _updateUserInteraction() {
    debugPrint('App: User interaction detected');
    SessionManager.updateLastUserInteraction();
  }
}

// Custom navigator observer to clear SnackBars when navigating to new screens
class _SnackBarClearingNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPush(route, previousRoute);
    _clearSnackBars();
  }

  @override
  void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
    super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
    _clearSnackBars();
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPop(route, previousRoute);
    _clearSnackBars();
  }

  void _clearSnackBars() {
    if (navigatorKey.currentContext != null) {
      ScaffoldMessenger.of(navigatorKey.currentContext!).hideCurrentSnackBar();
      ScaffoldMessenger.of(navigatorKey.currentContext!).clearSnackBars();
    }
  }
}

// Observer baru untuk mendeteksi navigasi pengguna sebagai bentuk interaksi
class _UserInteractionObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPush(route, previousRoute);
    debugPrint('App: Navigation interaction detected (push)');
    SessionManager.updateLastUserInteraction();
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    super.didPop(route, previousRoute);
    debugPrint('App: Navigation interaction detected (pop)');
    SessionManager.updateLastUserInteraction();
  }
}

// Add a utility function to show the debug FAB from anywhere
void showDebugFAB(BuildContext context) {
  WidgetsBinding.instance.addPostFrameCallback((_) {
    // Use the navigator key to navigate safely
    navigatorKey.currentState?.pushNamed('/image-test');
  });
}
