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/onboarding_store.dart';
import 'state/inventory_cubit.dart';
import 'state/variety_detail_cubit.dart';
import 'ui/about_screen.dart';
import 'ui/home_screen.dart';
import 'ui/intro_screen.dart';
import 'ui/inventory_list_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.showIntro = false,
    super.key,
  }) : _router = _buildRouter(repository, onboarding, showIntro);

  final VarietyRepository repository;
  final SpeciesRepository species;
  final OnboardingStore onboarding;
  final bool showIntro;
  final GoRouter _router;

  static GoRouter _buildRouter(
    VarietyRepository repository,
    OnboardingStore onboarding,
    bool showIntro,
  ) {
    return GoRouter(
      initialLocation: showIntro ? '/intro' : '/',
      routes: [
        GoRoute(path: '/', builder: (context, state) => const HomeScreen()),
        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: 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,
  };
}
