// lib/main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'dart:async'; // Import Timer

import 'package:provider/single_child_widget.dart';
import 'package:environment_monitoring_app/services/api_service.dart';
import 'package:environment_monitoring_app/services/local_storage_service.dart';
import 'package:environment_monitoring_app/services/river_in_situ_sampling_service.dart';
import 'package:environment_monitoring_app/services/river_manual_triennial_sampling_service.dart';
import 'package:environment_monitoring_app/services/air_sampling_service.dart';
import 'package:environment_monitoring_app/services/telegram_service.dart';
import 'package:environment_monitoring_app/services/server_config_service.dart';
import 'package:environment_monitoring_app/services/retry_service.dart';
import 'package:environment_monitoring_app/services/marine_in_situ_sampling_service.dart';
import 'package:environment_monitoring_app/services/marine_npe_report_service.dart';
import 'package:environment_monitoring_app/services/marine_tarball_sampling_service.dart';
import 'package:environment_monitoring_app/services/marine_manual_pre_departure_service.dart';
import 'package:environment_monitoring_app/services/marine_manual_sonde_calibration_service.dart';
import 'package:environment_monitoring_app/services/marine_manual_equipment_maintenance_service.dart';

import 'package:environment_monitoring_app/theme.dart';
import 'package:environment_monitoring_app/auth_provider.dart';

// Core Screens
import 'package:environment_monitoring_app/screens/login.dart';
import 'package:environment_monitoring_app/screens/register.dart';
import 'package:environment_monitoring_app/screens/forgot_password.dart';
import 'package:environment_monitoring_app/screens/logout.dart';
import 'package:environment_monitoring_app/home_page.dart';
import 'package:environment_monitoring_app/screens/profile.dart';
import 'package:environment_monitoring_app/screens/settings.dart';

// Department Home Pages
import 'package:environment_monitoring_app/screens/air/air_home_page.dart';
import 'package:environment_monitoring_app/screens/river/river_home_page.dart';
import 'package:environment_monitoring_app/screens/marine/marine_home_page.dart';

// Air Screens
import 'package:environment_monitoring_app/screens/air/manual/air_manual_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/air/manual/air_manual_installation_screen.dart';
import 'package:environment_monitoring_app/screens/air/manual/air_manual_collection_screen.dart';
import 'package:environment_monitoring_app/screens/air/manual/air_manual_report.dart' as airManualReport;
import 'package:environment_monitoring_app/screens/air/manual/air_manual_data_status_log.dart' as airManualDataStatusLog;
import 'package:environment_monitoring_app/screens/air/manual/air_manual_image_request.dart' as airManualImageRequest;
import 'package:environment_monitoring_app/screens/air/continuous/air_continuous_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/air/continuous/overview.dart' as airContinuousOverview;
import 'package:environment_monitoring_app/screens/air/continuous/entry.dart' as airContinuousEntry;
import 'package:environment_monitoring_app/screens/air/continuous/report.dart' as airContinuousReport;
import 'package:environment_monitoring_app/screens/air/investigative/air_investigative_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/air/investigative/overview.dart' as airInvestigativeOverview;
import 'package:environment_monitoring_app/screens/air/investigative/entry.dart' as airInvestigativeEntry;
import 'package:environment_monitoring_app/screens/air/investigative/report.dart' as airInvestigativeReport;

// River Screens
import 'package:environment_monitoring_app/screens/river/manual/river_manual_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/river/manual/in_situ_sampling.dart' as riverManualInSituSampling;
import 'package:environment_monitoring_app/screens/river/manual/river_manual_data_status_log.dart' as riverManualDataStatusLog;
import 'package:environment_monitoring_app/screens/river/manual/river_manual_report.dart' as riverManualReport;
import 'package:environment_monitoring_app/screens/river/manual/triennial/river_manual_triennial_sampling.dart' as riverManualTriennialSampling;
import 'package:environment_monitoring_app/screens/river/manual/river_manual_image_request.dart' as riverManualImageRequest;
import 'package:environment_monitoring_app/screens/river/continuous/river_continuous_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/river/continuous/overview.dart' as riverContinuousOverview;
import 'package:environment_monitoring_app/screens/river/continuous/entry.dart' as riverContinuousEntry;
import 'package:environment_monitoring_app/screens/river/continuous/report.dart' as riverContinuousReport;
import 'package:environment_monitoring_app/screens/river/investigative/river_investigative_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/river/investigative/overview.dart' as riverInvestigativeOverview;
import 'package:environment_monitoring_app/screens/river/investigative/entry.dart' as riverInvestigativeEntry;
import 'package:environment_monitoring_app/screens/river/investigative/report.dart' as riverInvestigativeReport;

// Marine Screens
import 'package:environment_monitoring_app/screens/marine/manual/info_centre_document.dart' as marineManualInfoCentreDocument;
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_pre_sampling.dart' as marineManualPreSampling;
import 'package:environment_monitoring_app/screens/marine/manual/in_situ_sampling.dart' as marineManualInSituSampling;
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_report.dart' as marineManualReport;
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_npe_report_hub.dart';
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_pre_departure_checklist_screen.dart' as marineManualPreDepartureChecklist;
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_sonde_calibration_screen.dart' as marineManualSondeCalibration;
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_equipment_maintenance_screen.dart' as marineManualEquipmentMaintenance;
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_data_status_log.dart' as marineManualDataStatusLog;
import 'package:environment_monitoring_app/screens/marine/manual/marine_image_request.dart' as marineManualImageRequest;
import 'package:environment_monitoring_app/screens/marine/continuous/marine_continuous_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/marine/continuous/overview.dart' as marineContinuousOverview;
import 'package:environment_monitoring_app/screens/marine/continuous/entry.dart' as marineContinuousEntry;
import 'package:environment_monitoring_app/screens/marine/continuous/report.dart' as marineContinuousReport;
import 'package:environment_monitoring_app/screens/marine/investigative/marine_investigative_info_centre_document.dart';
import 'package:environment_monitoring_app/screens/marine/investigative/overview.dart' as marineInvestigativeOverview;
import 'package:environment_monitoring_app/screens/marine/investigative/entry.dart' as marineInvestigativeEntry;
import 'package:environment_monitoring_app/screens/marine/investigative/report.dart' as marineInvestigativeReport;

import 'package:environment_monitoring_app/models/tarball_data.dart';
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step1.dart';
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step2.dart';
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step3_summary.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Create singleton instances of core services before running the app
  final DatabaseHelper databaseHelper = DatabaseHelper();
  final TelegramService telegramService = TelegramService();
  final ApiService apiService = ApiService(telegramService: telegramService);
  final RetryService retryService = RetryService();
  final MarineInSituSamplingService marineInSituService = MarineInSituSamplingService(telegramService);
  final RiverInSituSamplingService riverInSituService = RiverInSituSamplingService(telegramService);

  telegramService.setApiService(apiService);

  // The AuthProvider needs to be created here so it can be passed to the retry service.
  final authProvider = AuthProvider(
    apiService: apiService,
    dbHelper: databaseHelper,
    serverConfigService: ServerConfigService(),
    retryService: retryService,
  );

  // Initialize the retry service with all its dependencies.
  retryService.initialize(
    marineInSituService: marineInSituService,
    riverInSituService: riverInSituService,
    authProvider: authProvider,
  );

  setupPeriodicServices(telegramService, retryService);

  runApp(
    MultiProvider(
      providers: <SingleChildWidget>[
        ChangeNotifierProvider.value(value: authProvider),
        Provider<ApiService>(create: (_) => apiService),
        Provider<DatabaseHelper>(create: (_) => databaseHelper),
        Provider<TelegramService>(create: (_) => telegramService),
        Provider(create: (_) => LocalStorageService()),
        Provider.value(value: retryService),
        Provider.value(value: marineInSituService),
        Provider.value(value: riverInSituService),
        Provider(create: (context) => RiverManualTriennialSamplingService(telegramService)),
        Provider(create: (context) => AirSamplingService(databaseHelper, telegramService)),
        Provider(create: (context) => MarineTarballSamplingService(telegramService)),
        Provider(create: (context) => MarineNpeReportService(Provider.of<TelegramService>(context, listen: false))),
        Provider(create: (context) => MarineManualPreDepartureService()),
        Provider(create: (context) => MarineManualSondeCalibrationService()),
        Provider(create: (context) => MarineManualEquipmentMaintenanceService()),
      ],
      child: const RootApp(),
    ),
  );
}

void setupPeriodicServices(TelegramService telegramService, RetryService retryService) {
  // Initial processing on startup (delayed)
  Future.delayed(const Duration(seconds: 5), () {
    debugPrint("[Main] Performing initial alert queue processing on app start.");
    telegramService.processAlertQueue();
    debugPrint("[Main] Performing initial retry queue processing on app start.");
    retryService.processRetryQueue();
  });

  // Start recurring timers to process both queues every 5 minutes.
  Timer.periodic(const Duration(minutes: 5), (timer) {
    debugPrint("[Main] Periodic check: Processing Telegram alert queue...");
    telegramService.processAlertQueue();
    debugPrint("[Main] Periodic check: Processing main retry queue...");
    retryService.processRetryQueue();
  });
}

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

  @override
  State<RootApp> createState() => _RootAppState();
}

class _RootAppState extends State<RootApp> {

  @override
  void initState() {
    super.initState();
    _initializeConnectivityListener();
    _performInitialSessionCheck();
  }

  /// Initial check when app loads to see if we need to transition from offline to online.
  void _performInitialSessionCheck() async {
    // Wait a moment for providers to be fully available.
    await Future.delayed(const Duration(milliseconds: 100));
    if (mounted) {
      final authProvider = Provider.of<AuthProvider>(context, listen: false);

      // Perform proactive token refresh on app start
      await authProvider.proactiveTokenRefresh();

      // First, try to transition from an offline placeholder token to an online one.
      final didTransition = await authProvider.checkAndTransitionToOnlineSession();
      // If no transition happened (i.e., we were already supposed to be online), validate the session.
      if (!didTransition) {
        authProvider.validateAndRefreshSession();
      }
    }
  }

  /// Listens for connectivity changes to trigger auto-relogin or queue processing.
  void _initializeConnectivityListener() {
    Connectivity().onConnectivityChanged.listen((List<ConnectivityResult> results) {
      if (!results.contains(ConnectivityResult.none)) {
        debugPrint("[Main] Internet connection detected.");
        if (mounted) {
          // Access services from provider context
          final authProvider = Provider.of<AuthProvider>(context, listen: false);
          final telegramService = Provider.of<TelegramService>(context, listen: false);
          final retryService = Provider.of<RetryService>(context, listen: false);

          // When connection is restored, always try to transition/validate the session.
          authProvider.checkAndTransitionToOnlineSession().then((didTransition) {
            if (!didTransition) {
              authProvider.validateAndRefreshSession();
            }
          });

          // Process queues
          telegramService.processAlertQueue();
          retryService.processRetryQueue();
        }
      } else {
        debugPrint("[Main] Internet connection lost.");
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<AuthProvider>(
      builder: (context, auth, child) {
        Widget homeWidget;
        if (auth.isLoading) {
          homeWidget = const SplashScreen();
        } else if (auth.isLoggedIn) {
          homeWidget = const SessionAwareWrapper(child: HomePage());
        } else {
          homeWidget = const LoginScreen();
        }

        return MaterialApp(
          title: 'Environment Monitoring App',
          theme: AppTheme.darkBlueTheme,
          debugShowCheckedModeBanner: false,
          home: homeWidget,

          onGenerateRoute: (settings) {
            if (settings.name == '/marine/manual/tarball/step2') {
              final args = settings.arguments as TarballSamplingData;
              return MaterialPageRoute(builder: (context) {
                return TarballSamplingStep2(data: args);
              });
            }
            if (settings.name == '/marine/manual/tarball/step3') {
              final args = settings.arguments as TarballSamplingData;
              return MaterialPageRoute(builder: (context) {
                return TarballSamplingStep3Summary(data: args);
              });
            }
            if (settings.name == '/marine/manual/data-log') {
              return MaterialPageRoute(builder: (context) {
                return const marineManualDataStatusLog.MarineManualDataStatusLog();
              });
            }
            return null;
          },
          routes: {
            // Auth Routes
            '/register': (context) => const RegisterScreen(),
            '/forgot-password': (context) => ForgotPasswordScreen(),
            '/logout': (context) => const LogoutScreen(),
            '/home': (context) => const HomePage(),
            '/profile': (context) => const ProfileScreen(),
            '/settings': (context) => const SettingsScreen(),

            // Department Home Pages
            '/air/home': (context) => const AirHomePage(),
            '/river/home': (context) => const RiverHomePage(),
            '/marine/home': (context) => const MarineHomePage(),

            // Air Manual
            '/air/manual/info': (context) => const AirManualInfoCentreDocument(),
            '/air/manual/installation': (context) => const AirManualInstallationScreen(),
            '/air/manual/collection': (context) => const AirManualCollectionScreen(),
            '/air/manual/report': (context) => airManualReport.AirManualReport(),
            '/air/manual/data-log': (context) => airManualDataStatusLog.AirManualDataStatusLog(),
            '/air/manual/image-request': (context) => airManualImageRequest.AirManualImageRequest(),

            // Air Continuous
            '/air/continuous/info': (context) => const AirContinuousInfoCentreDocument(),
            '/air/continuous/overview': (context) => airContinuousOverview.OverviewScreen(),
            '/air/continuous/entry': (context) => airContinuousEntry.EntryScreen(),
            '/air/continuous/report': (context) => airContinuousReport.ReportScreen(),

            // Air Investigative
            '/air/investigative/info': (context) => const AirInvestigativeInfoCentreDocument(),
            '/air/investigative/overview': (context) => airInvestigativeOverview.OverviewScreen(),
            '/air/investigative/entry': (context) => airInvestigativeEntry.EntryScreen(),
            '/air/investigative/report': (context) => airInvestigativeReport.ReportScreen(),

            // River Manual
            '/river/manual/info': (context) => const RiverManualInfoCentreDocument(),
            '/river/manual/in-situ': (context) => riverManualInSituSampling.RiverInSituSamplingScreen(),
            '/river/manual/report': (context) => riverManualReport.RiverManualReport(),
            '/river/manual/triennial': (context) => riverManualTriennialSampling.RiverManualTriennialSamplingScreen(),
            '/river/manual/data-log': (context) => riverManualDataStatusLog.RiverManualDataStatusLog(),
            '/river/manual/image-request': (context) => riverManualImageRequest.RiverManualImageRequest(),

            // River Continuous
            '/river/continuous/info': (context) => const RiverContinuousInfoCentreDocument(),
            '/river/continuous/overview': (context) => riverContinuousOverview.OverviewScreen(),
            '/river/continuous/entry': (context) => riverContinuousEntry.EntryScreen(),
            '/river/continuous/report': (context) => riverContinuousReport.ReportScreen(),

            // River Investigative
            '/river/investigative/info': (context) => const RiverInvestigativeInfoCentreDocument(),
            '/river/investigative/overview': (context) => riverInvestigativeOverview.OverviewScreen(),
            '/river/investigative/entry': (context) => riverInvestigativeEntry.EntryScreen(),
            '/river/investigative/report': (context) => riverInvestigativeReport.ReportScreen(),

            // Marine Manual
            '/marine/manual/info': (context) => marineManualInfoCentreDocument.MarineInfoCentreDocument(),
            '/marine/manual/pre-sampling': (context) => marineManualPreSampling.MarineManualPreSampling(),
            '/marine/manual/in-situ': (context) => marineManualInSituSampling.MarineInSituSampling(),
            '/marine/manual/tarball': (context) => const TarballSamplingStep1(),
            '/marine/manual/report': (context) => const marineManualReport.MarineManualReportHomePage(),
            '/marine/manual/report/npe': (context) => const MarineManualNPEReportHub(),
            '/marine/manual/report/pre-departure': (context) => const marineManualPreDepartureChecklist.MarineManualPreDepartureChecklistScreen(),
            '/marine/manual/report/calibration': (context) => const marineManualSondeCalibration.MarineManualSondeCalibrationScreen(),
            '/marine/manual/report/maintenance': (context) => const marineManualEquipmentMaintenance.MarineManualEquipmentMaintenanceScreen(),
            '/marine/manual/image-request': (context) => const marineManualImageRequest.MarineImageRequestScreen(),

            // Marine Continuous
            '/marine/continuous/info': (context) => const MarineContinuousInfoCentreDocument(),
            '/marine/continuous/overview': (context) => marineContinuousOverview.OverviewScreen(),
            '/marine/continuous/entry': (context) => marineContinuousEntry.EntryScreen(),
            '/marine/continuous/report': (context) => marineContinuousReport.ReportScreen(),

            // Marine Investigative
            '/marine/investigative/info': (context) => const MarineInvestigativeInfoCentreDocument(),
            '/marine/investigative/overview': (context) => marineInvestigativeOverview.OverviewScreen(),
            '/marine/investigative/entry': (context) => marineInvestigativeEntry.EntryScreen(),
            '/marine/investigative/report': (context) => marineInvestigativeReport.ReportScreen(),
          },
        );
      },
    );
  }
}

class SessionAwareWrapper extends StatefulWidget {
  final Widget child;
  const SessionAwareWrapper({super.key, required this.child});

  @override
  State<SessionAwareWrapper> createState() => _SessionAwareWrapperState();
}

class _SessionAwareWrapperState extends State<SessionAwareWrapper> {
  bool _isDialogShowing = false;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final auth = Provider.of<AuthProvider>(context);

    if (auth.isSessionExpired && !_isDialogShowing) {
      // Use addPostFrameCallback to show dialog after the build phase.
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _showSessionExpiredDialog();
      });
    }
  }

  Future<void> _showSessionExpiredDialog() async {
    setState(() => _isDialogShowing = true);
    await showDialog(
      context: context,
      barrierDismissible: false, // User must make a choice
      builder: (BuildContext dialogContext) {
        final auth = Provider.of<AuthProvider>(context, listen: false);
        return AlertDialog(
          title: const Text("Session Expired"),
          content: const Text(
              "Your online session has expired. You can continue working offline, but you will not be able to sync data until you log in again."),
          actions: <Widget>[
            TextButton(
              child: const Text("Continue Offline"),
              onPressed: () {
                Navigator.of(dialogContext).pop(); // Just close the dialog
              },
            ),
            ElevatedButton(
              child: const Text("Login Now"),
              onPressed: () {
                // Logout clears all state and pushes to login screen via the RootApp builder
                auth.logout();
                Navigator.of(dialogContext).pop();
              },
            ),
          ],
        );
      },
    );
    // Once the dialog is dismissed, reset the flag.
    if (mounted) {
      setState(() => _isDialogShowing = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    // This widget just returns its child, its only job is to show the dialog.
    return widget.child;
  }
}

class SplashScreen extends StatelessWidget {
  const SplashScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.asset(
              'assets/icon4.png', // Ensure this asset exists
              height: 360,
              width: 360,
            ),
            const SizedBox(height: 24),
            const CircularProgressIndicator(),
            const SizedBox(height: 20),
            const Text('Loading MMS data...', style: TextStyle(fontSize: 16)),
          ],
        ),
      ),
    );
  }
}