import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:geolocator/geolocator.dart';
import 'package:url_launcher/url_launcher.dart';
import 'providers/connection_provider.dart';
import 'providers/contacts_provider.dart';
import 'providers/messages_provider.dart';
import 'providers/map_provider.dart';
import 'providers/drawing_provider.dart';
import 'providers/channels_provider.dart';
import 'providers/voice_provider.dart';
import 'providers/image_provider.dart' as ip;
import 'providers/app_provider.dart';
import 'services/voice_codec_service.dart';
import 'services/voice_player_service.dart';
import 'services/tile_cache_service.dart';
import 'services/notification_service.dart';
import 'services/locale_preferences.dart';
import 'services/update_checker_service.dart';
import 'services/wizard_preferences.dart';
import 'screens/home_screen.dart';
import 'screens/welcome_wizard_screen.dart';
import 'theme/app_theme.dart';
import 'l10n/app_localizations.dart';

void main() {
  runApp(const MeshCoreSarApp());
}

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

  @override
  State<MeshCoreSarApp> createState() => _MeshCoreSarAppState();
}

class _MeshCoreSarAppState extends State<MeshCoreSarApp> {
  AppThemeMode _themeMode = AppThemeMode.system;
  Locale? _locale;
  bool _isInitialized = false;
  bool _shouldShowPermissionDialog = false;
  bool _wizardCompleted = true; // Will be updated in _initializeApp()

  @override
  void initState() {
    super.initState();
    _initializeApp();
  }

  Future<void> _initializeApp() async {
    await _loadThemePreference();
    await _loadLocalePreference();

    // Check if welcome wizard has been completed
    final wizardCompleted = await WizardPreferences.isWizardCompleted();

    // Initialize notification service
    await NotificationService().initialize();

    // Set up notification tap handler for update notifications
    NotificationService().onNotificationTapped = _handleNotificationTap;

    // Check if we need to request location permissions
    await _checkLocationPermissions();

    // Check for app updates (Android only) - runs in background
    // Shows notification if update is available
    _checkForUpdates();

    setState(() {
      _wizardCompleted = wizardCompleted;
      _isInitialized = true;
    });
  }

  /// Handle notification tap
  void _handleNotificationTap(String? payload) {
    if (payload == null) return;

    debugPrint('[Main] Notification tapped: $payload');

    // Handle update notification tap
    if (payload.startsWith('update:')) {
      final downloadUrl = payload.substring(7); // Remove 'update:' prefix
      _launchUpdateDownload(downloadUrl);
    }
    // SAR and message notifications handled by their respective providers
  }

  /// Launch update download URL
  Future<void> _launchUpdateDownload(String downloadUrl) async {
    try {
      final url = Uri.parse(downloadUrl);
      final canLaunch = await canLaunchUrl(url);

      if (!canLaunch) {
        debugPrint('[Main] Cannot open download URL: $downloadUrl');
        return;
      }

      await launchUrl(url, mode: LaunchMode.externalApplication);
    } catch (e) {
      debugPrint('[Main] Error launching download URL: $e');
    }
  }

  Future<void> _checkLocationPermissions() async {
    try {
      final permission = await Geolocator.checkPermission();

      // Show dialog if permission is denied or not determined
      if (permission == LocationPermission.denied ||
          permission == LocationPermission.deniedForever) {
        _shouldShowPermissionDialog = true;
      }
    } catch (e) {
      debugPrint('Error checking location permissions: $e');
    }
  }

  Future<void> _loadThemePreference() async {
    final prefs = await SharedPreferences.getInstance();
    final themeName = prefs.getString('theme_mode') ?? 'system';
    setState(() {
      _themeMode = AppTheme.themeFromString(themeName);
    });
  }

  Future<void> _loadLocalePreference() async {
    final locale = await LocalePreferences.getLocale();
    setState(() {
      _locale = locale;
    });
  }

  void _handleThemeChanged(AppThemeMode mode) {
    setState(() {
      _themeMode = mode;
    });
  }

  void _handleLocaleChanged(Locale? locale) {
    setState(() {
      _locale = locale;
    });
  }

  void _handleWizardCompleted() {
    setState(() {
      _wizardCompleted = true;
    });
  }

  /// Check for app updates on Android only
  /// Shows notification if update is available
  Future<void> _checkForUpdates() async {
    // Only check for updates on Android
    if (!Platform.isAndroid) {
      debugPrint('[UpdateChecker] Skipping update check (not Android)');
      return;
    }

    try {
      debugPrint('[UpdateChecker] Starting update check...');
      final updateInfo = await UpdateCheckerService().checkForUpdate();

      if (!updateInfo.isAvailable) {
        debugPrint('[UpdateChecker] No update available');
        return;
      }

      if (updateInfo.downloadUrl == null) {
        debugPrint('[UpdateChecker] Update available but no download URL');
        return;
      }

      debugPrint('[UpdateChecker] Update available! Showing notification...');

      // Show notification (will be visible after app is initialized)
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        if (mounted) {
          await NotificationService().showUpdateNotification(
            currentVersion: updateInfo.currentCommitHash,
            latestVersion: updateInfo.latestCommitHash ?? 'unknown',
            downloadUrl: updateInfo.downloadUrl!,
            localizations: null, // Will use English fallback
          );
        }
      });
    } catch (e) {
      debugPrint('[UpdateChecker] Error checking for updates: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    if (!_isInitialized) {
      return const MaterialApp(
        home: Scaffold(body: Center(child: CircularProgressIndicator())),
      );
    }

    return MultiProvider(
      providers: [
        // Core providers
        ChangeNotifierProvider(create: (_) => ConnectionProvider()),
        ChangeNotifierProvider(
          create: (_) {
            // Initialize early to load persisted contacts for offline viewing
            // Self-contact filtering will happen later when BLE connects
            final provider = ContactsProvider();
            provider.initializeEarly();
            return provider;
          },
        ),
        ChangeNotifierProvider(
          create: (_) {
            final provider = MessagesProvider();
            // Initialize messages provider asynchronously
            provider.initialize();
            return provider;
          },
        ),
        ChangeNotifierProvider(create: (_) => MapProvider()),
        ChangeNotifierProvider(
          create: (_) {
            final provider = DrawingProvider();
            // Initialize drawing provider asynchronously
            provider.initialize();
            return provider;
          },
        ),
        ChangeNotifierProvider(create: (_) => ChannelsProvider()),

        // Voice provider (packet reassembly + playback)
        ChangeNotifierProvider(
          create: (_) => VoiceProvider(
            codec: VoiceCodecService(),
            player: VoicePlayerService(),
          ),
        ),

        // Image provider (fragment reassembly + outgoing session cache)
        ChangeNotifierProvider(create: (_) => ip.ImageProvider()),

        // Tile cache service
        Provider(create: (_) => TileCacheService()),

        // App provider that coordinates everything
        // VoiceProvider is read via context.read inside create since it's already registered above
        ChangeNotifierProxyProvider6<
          ConnectionProvider,
          ContactsProvider,
          MessagesProvider,
          DrawingProvider,
          ChannelsProvider,
          TileCacheService,
          AppProvider
        >(
          create: (context) => AppProvider(
            connectionProvider: context.read<ConnectionProvider>(),
            contactsProvider: context.read<ContactsProvider>(),
            messagesProvider: context.read<MessagesProvider>(),
            drawingProvider: context.read<DrawingProvider>(),
            channelsProvider: context.read<ChannelsProvider>(),
            voiceProvider: context.read<VoiceProvider>(),
            imageProvider: context.read<ip.ImageProvider>(),
            tileCacheService: context.read<TileCacheService>(),
          ),
          update:
              (
                context,
                conn,
                contacts,
                messages,
                drawings,
                channels,
                tileCache,
                previous,
              ) =>
                  previous ??
                  AppProvider(
                    connectionProvider: conn,
                    contactsProvider: contacts,
                    messagesProvider: messages,
                    drawingProvider: drawings,
                    channelsProvider: channels,
                    voiceProvider: context.read<VoiceProvider>(),
                    imageProvider: context.read<ip.ImageProvider>(),
                    tileCacheService: tileCache,
                  ),
        ),
      ],
      child: _buildMaterialApp(),
    );
  }

  Widget _buildMaterialApp() {
    return Builder(
      builder: (context) {
        final systemBrightness = MediaQuery.platformBrightnessOf(context);
        final materialApp = MaterialApp(
          key: ValueKey<String?>(
            '${_locale?.languageCode ?? 'system'}_${_themeMode.name}',
          ),
          title: 'MeshCore SAR',
          debugShowCheckedModeBanner: false,
          theme: AppTheme.getTheme(_themeMode, systemBrightness),
          locale: _locale,
          localizationsDelegates: const [
            AppLocalizations.delegate,
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          supportedLocales: LocalePreferences.supportedLocales,
          home: _wizardCompleted
              ? HomeScreen(
                  onThemeChanged: _handleThemeChanged,
                  onLocaleChanged: _handleLocaleChanged,
                  currentTheme: _themeMode,
                  currentLocale: _locale,
                  shouldShowPermissionDialog: _shouldShowPermissionDialog,
                )
              : WelcomeWizardScreen(onCompleted: _handleWizardCompleted),
        );

        // Wrap in SafeArea for Android only to fix navigation bar overlap (API ≥36)
        // iOS doesn't need SafeArea wrapping (causes extra black space at bottom)
        if (Platform.isAndroid) {
          return SafeArea(
            left: false,
            right: false,
            top: false, // prevents black status bar background
            child: materialApp,
          );
        }

        return materialApp;
      },
    );
  }
}
