import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotiflac_android/l10n/l10n.dart';
import 'package:spotiflac_android/providers/download_queue_provider.dart';
import 'package:spotiflac_android/providers/settings_provider.dart';
import 'package:spotiflac_android/providers/store_provider.dart';
import 'package:spotiflac_android/providers/track_provider.dart';
import 'package:spotiflac_android/screens/home_tab.dart';
import 'package:spotiflac_android/screens/store_tab.dart';
import 'package:spotiflac_android/screens/queue_tab.dart';
import 'package:spotiflac_android/screens/settings/settings_tab.dart';
import 'package:spotiflac_android/services/share_intent_service.dart';
import 'package:spotiflac_android/services/update_checker.dart';
import 'package:spotiflac_android/widgets/update_dialog.dart';
import 'package:spotiflac_android/utils/logger.dart';

final _log = AppLogger('MainShell');

class MainShell extends ConsumerStatefulWidget {
  const MainShell({super.key});

  @override
  ConsumerState<MainShell> createState() => _MainShellState();
}

class _MainShellState extends ConsumerState<MainShell> {
  int _currentIndex = 0;
  late PageController _pageController;
  bool _hasCheckedUpdate = false;
  StreamSubscription<String>? _shareSubscription;
  DateTime? _lastBackPress;

  @override
  void initState() {
    super.initState();
    _pageController = PageController(initialPage: _currentIndex);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _checkForUpdates();
      _setupShareListener();
    });
  }

  void _setupShareListener() {
    final pendingUrl = ShareIntentService().consumePendingUrl();
    if (pendingUrl != null) {
      _log.d('Processing pending shared URL: $pendingUrl');
      _handleSharedUrl(pendingUrl);
    }

    _shareSubscription = ShareIntentService().sharedUrlStream.listen(
      (url) {
        _log.d('Received shared URL from stream: $url');
        _handleSharedUrl(url);
      },
      onError: (error) {
        _log.e('Share stream error: $error');
      },
      cancelOnError: false,
    );
  }

  void _handleSharedUrl(String url) {
    Navigator.of(context).popUntil((route) => route.isFirst);
    
    if (_currentIndex != 0) {
      _onNavTap(0);
    }
    ref.read(trackProvider.notifier).fetchFromUrl(url);
    ref.read(settingsProvider.notifier).setHasSearchedBefore();
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(context.l10n.loadingSharedLink)),
      );
    }
  }

  Future<void> _checkForUpdates() async {
    if (_hasCheckedUpdate) return;
    _hasCheckedUpdate = true;

    final settings = ref.read(settingsProvider);
    if (!settings.checkForUpdates) return;

    final updateInfo = await UpdateChecker.checkForUpdate(channel: settings.updateChannel);
    if (updateInfo != null && mounted) {
      showUpdateDialog(
        context,
        updateInfo: updateInfo,
        onDisableUpdates: () {
          ref.read(settingsProvider.notifier).setCheckForUpdates(false);
        },
      );
    }
  }

  @override
  void dispose() {
    _shareSubscription?.cancel();
    _pageController.dispose();
    super.dispose();
  }

  void _onNavTap(int index) {
    if (_currentIndex != index) {
      setState(() => _currentIndex = index);
      _pageController.animateToPage(
        index,
        duration: const Duration(milliseconds: 250),
        curve: Curves.easeOutCubic,
      );
    }
  }

  void _onPageChanged(int index) {
    if (_currentIndex != index) {
      setState(() => _currentIndex = index);
      FocusManager.instance.primaryFocus?.unfocus();
    }
  }

  void _handleBackPress() {
    final trackState = ref.read(trackProvider);
    
    final isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom > 0;
    if (isKeyboardVisible) {
      FocusManager.instance.primaryFocus?.unfocus();
      return;
    }
    
    if (_currentIndex == 0 && trackState.isShowingRecentAccess) {
      ref.read(trackProvider.notifier).setShowingRecentAccess(false);
      FocusManager.instance.primaryFocus?.unfocus();
      return;
    }
    
    if (_currentIndex == 0 && !trackState.isLoading && (trackState.hasSearchText || trackState.hasContent)) {
      ref.read(trackProvider.notifier).clear();
      return;
    }
    
    if (_currentIndex != 0) {
      _onNavTap(0);
      return;
    }
    
    if (trackState.isLoading) {
      return;
    }
    
    final now = DateTime.now();
    if (_lastBackPress != null && now.difference(_lastBackPress!) < const Duration(seconds: 2)) {
      SystemNavigator.pop();
    } else {
      _lastBackPress = now;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(context.l10n.pressBackAgainToExit),
          duration: const Duration(seconds: 2),
          behavior: SnackBarBehavior.floating,
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    final queueState = ref.watch(downloadQueueProvider.select((s) => s.queuedCount));
    final trackState = ref.watch(trackProvider);
    final showStore = ref.watch(settingsProvider.select((s) => s.showExtensionStore));
    final storeUpdatesCount = ref.watch(storeProvider.select((s) => s.updatesAvailableCount));
    
    final isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom > 0;
    
    final canPop = _currentIndex == 0 && 
                   !trackState.hasSearchText && 
                   !trackState.hasContent && 
                   !trackState.isLoading &&
                   !trackState.isShowingRecentAccess &&
                   !isKeyboardVisible;

    final tabs = <Widget>[
      const HomeTab(),
      QueueTab(
        parentPageController: _pageController,
        parentPageIndex: 1,
        nextPageIndex: showStore ? 2 : 3,
      ),
      if (showStore) const StoreTab(),
      const SettingsTab(),
    ];

    final l10n = context.l10n;
    final destinations = <NavigationDestination>[
      NavigationDestination(
        icon: const Icon(Icons.home_outlined),
        selectedIcon: const Icon(Icons.home),
        label: l10n.navHome,
      ),
      NavigationDestination(
        icon: Badge(
          isLabelVisible: queueState > 0,
          label: Text('$queueState'),
          child: const Icon(Icons.history_outlined),
        ),
        selectedIcon: Badge(
          isLabelVisible: queueState > 0,
          label: Text('$queueState'),
          child: const Icon(Icons.history),
        ),
        label: l10n.navHistory,
      ),
      if (showStore)
        NavigationDestination(
          icon: Badge(
            isLabelVisible: storeUpdatesCount > 0,
            label: Text('$storeUpdatesCount'),
            child: const Icon(Icons.store_outlined),
          ),
          selectedIcon: Badge(
            isLabelVisible: storeUpdatesCount > 0,
            label: Text('$storeUpdatesCount'),
            child: const Icon(Icons.store),
          ),
          label: l10n.navStore,
        ),
      NavigationDestination(
        icon: const Icon(Icons.settings_outlined),
        selectedIcon: const Icon(Icons.settings),
        label: l10n.navSettings,
      ),
    ];

    final maxIndex = tabs.length - 1;
    if (_currentIndex > maxIndex) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          setState(() => _currentIndex = maxIndex);
          _pageController.jumpToPage(maxIndex);
        }
      });
    }

    return PopScope(
      canPop: canPop,
      onPopInvokedWithResult: (didPop, result) async {
        if (didPop) {
          return;
        }
        
        _handleBackPress();
      },
      child: Scaffold(
        body: PageView(
          controller: _pageController,
          onPageChanged: _onPageChanged,
          physics: const ClampingScrollPhysics(),
          children: tabs,
        ),
        bottomNavigationBar: NavigationBar(
          selectedIndex: _currentIndex.clamp(0, maxIndex),
          onDestinationSelected: _onNavTap,
          animationDuration: const Duration(milliseconds: 200),
          backgroundColor: Theme.of(context).brightness == Brightness.dark
              ? Color.alphaBlend(Colors.white.withValues(alpha: 0.05), Theme.of(context).colorScheme.surface)
              : Color.alphaBlend(Colors.black.withValues(alpha: 0.03), Theme.of(context).colorScheme.surface),
          destinations: destinations,
        ),
      ),
    );
  }
}
