import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:go_router/go_router.dart';

import 'data/species_repository.dart';
import 'data/variety_repository.dart';
import 'i18n/strings.g.dart';
import 'services/auto_backup_service.dart';
import 'services/coarse_location.dart';
import 'services/message_store.dart';
import 'services/offer_outbox.dart';
import 'services/onboarding_store.dart';
import 'services/social_service.dart';
import 'services/social_settings.dart';
import 'state/inventory_cubit.dart';
import 'state/variety_detail_cubit.dart';
import 'ui/about_screen.dart';
import 'ui/auto_backup_gate.dart';
import 'ui/chat_list_screen.dart';
import 'ui/chat_screen.dart';
import 'ui/home_screen.dart';
import 'ui/intro_screen.dart';
import 'ui/inventory_list_screen.dart';
import 'ui/market_screen.dart';
import 'ui/settings_screen.dart';
import 'ui/theme.dart';
import 'ui/variety_detail_screen.dart';

/// Root widget. Provides the repositories to the tree and wires go_router:
/// `/` is the home menu, `/inventory` the list, `/variety/:id` the item detail.
/// When [showIntro] is set (first launch), the app opens on `/intro`.
class TaneApp extends StatelessWidget {
  TaneApp({
    required this.repository,
    required this.species,
    required this.onboarding,
    this.social,
    this.socialSettings,
    this.location,
    this.outbox,
    this.messageStore,
    this.showIntro = false,
    this.autoBackup,
    super.key,
  }) : _router = _buildRouter(
          repository,
          onboarding,
          showIntro,
          social,
          socialSettings,
          location,
          outbox,
          messageStore,
        );

  final VarietyRepository repository;
  final SpeciesRepository species;
  final OnboardingStore onboarding;

  /// Block 2 social layer. Null until the social round is wired in `main`; when
  /// null the market stays a "coming soon" card and `/market` is not routed.
  final SocialService? social;
  final SocialSettings? socialSettings;

  /// Optional device-location source for the market's "use my location".
  final CoarseLocationProvider? location;

  /// Optional offline outbox for the market's "share my seeds".
  final OfferOutbox? outbox;

  /// Optional persistence for chat history.
  final MessageStore? messageStore;
  final bool showIntro;

  /// Drives silent periodic backups off the app lifecycle. Null in widget tests
  /// and on platforms without file storage (web) — the gate then does nothing.
  final AutoBackupService? autoBackup;
  final GoRouter _router;

  static GoRouter _buildRouter(
    VarietyRepository repository,
    OnboardingStore onboarding,
    bool showIntro,
    SocialService? social,
    SocialSettings? socialSettings,
    CoarseLocationProvider? location,
    OfferOutbox? outbox,
    MessageStore? messageStore,
  ) {
    return GoRouter(
      initialLocation: showIntro ? '/intro' : '/',
      routes: [
        GoRoute(
          path: '/',
          builder: (context, state) =>
              HomeScreen(marketEnabled: social != null),
        ),
        if (social != null && socialSettings != null)
          GoRoute(
            path: '/market',
            builder: (context, state) => MarketScreen(
              social: social,
              settings: socialSettings,
              location: location,
              outbox: outbox,
            ),
          ),
        if (social != null && socialSettings != null && messageStore != null)
          GoRoute(
            path: '/messages',
            builder: (context, state) => ChatListScreen(store: messageStore),
          ),
        if (social != null && socialSettings != null)
          GoRoute(
            path: '/chat/:pubkey',
            builder: (context, state) => ChatScreen(
              social: social,
              settings: socialSettings,
              peerPubkey: state.pathParameters['pubkey']!,
              messageStore: messageStore,
            ),
          ),
        GoRoute(
          path: '/intro',
          builder: (context, state) => IntroScreen(
            onDone: () async {
              await onboarding.markIntroSeen();
              if (context.mounted) context.go('/');
            },
          ),
        ),
        GoRoute(
          path: '/settings',
          builder: (context, state) => const SettingsScreen(),
        ),
        GoRoute(
          path: '/about',
          builder: (context, state) => const AboutScreen(),
        ),
        GoRoute(
          path: '/inventory',
          builder: (context, state) => BlocProvider(
            create: (_) => InventoryCubit(repository),
            child: const InventoryListScreen(),
          ),
        ),
        GoRoute(
          path: '/variety/:id',
          builder: (context, state) => BlocProvider(
            create: (_) =>
                VarietyDetailCubit(repository, state.pathParameters['id']!),
            child: const VarietyDetailScreen(),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return MultiRepositoryProvider(
      providers: [
        RepositoryProvider.value(value: repository),
        RepositoryProvider.value(value: species),
      ],
      child: AutoBackupGate(
        service: autoBackup,
        child: MaterialApp.router(
          onGenerateTitle: (context) => context.t.app.title,
          debugShowCheckedModeBanner: false,
          theme: buildTaneTheme(),
          // Let scrollables & PageViews be dragged with a mouse/trackpad on
          // desktop (Flutter disables that by default), so the photo carousel and
          // lists swipe there too.
          scrollBehavior: const _DragScrollBehavior(),
          locale: TranslationProvider.of(context).flutterLocale,
          supportedLocales: AppLocaleUtils.supportedLocales,
          localizationsDelegates: const [
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          routerConfig: _router,
        ),
      ),
    );
  }
}

/// Enables mouse/trackpad drag scrolling (off by default on desktop) so the
/// photo carousel and lists can be swiped with a pointer.
class _DragScrollBehavior extends MaterialScrollBehavior {
  const _DragScrollBehavior();

  @override
  Set<PointerDeviceKind> get dragDevices => {
    PointerDeviceKind.touch,
    PointerDeviceKind.mouse,
    PointerDeviceKind.trackpad,
    PointerDeviceKind.stylus,
  };
}
