import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';

import 'package:agenda_tasks/l10n/app_localizations.dart';
import 'package:agenda_tasks/features/onboarding/presentation/pages/setup_page.dart';
import 'package:agenda_tasks/features/settings/presentation/viewmodels/settings_viewmodel.dart';
import 'package:agenda_tasks/features/settings/domain/enums/app_mode.dart';
import 'package:agenda_tasks/features/settings/data/settings_local_datasource.dart';
import 'package:agenda_tasks/core/logging/app_logger.dart';

// Manual mock for SettingsLocalDataSource
class MockSettingsLocalDataSource implements SettingsLocalDataSource {
  AppMode? _appMode;
  bool _setupCompleted = false;
  bool _onboardingShown = false;
  Locale? _locale;
  ThemeMode _themeMode = ThemeMode.system;

  @override
  AppMode? getAppMode() => _appMode;

  @override
  Future<void> setAppMode(AppMode mode) async {
    _appMode = mode;
  }

  @override
  bool isSetupCompleted() => _setupCompleted;

  @override
  Future<void> setSetupCompleted(bool completed) async {
    _setupCompleted = completed;
  }

  @override
  bool isOnboardingShown() => _onboardingShown;

  @override
  Future<void> setOnboardingShown(bool shown) async {
    _onboardingShown = shown;
  }

  @override
  Locale? getLocale() => _locale;

  @override
  Future<void> setLocale(Locale locale) async {
    _locale = locale;
  }

  @override
  ThemeMode getThemeMode() => _themeMode;

  @override
  Future<void> setThemeMode(ThemeMode mode) async {
    _themeMode = mode;
  }
}

// Manual mock for AppLogger
class MockAppLogger extends AppLogger {
  @override
  void debug(String message, [dynamic error, StackTrace? stackTrace]) {}

  @override
  void info(String message, [dynamic error, StackTrace? stackTrace]) {}

  @override
  void warning(String message, [dynamic error, StackTrace? stackTrace]) {}

  @override
  void error(String message, [dynamic error, StackTrace? stackTrace]) {}

  @override
  void verbose(String message, [dynamic error, StackTrace? stackTrace]) {}
}

void main() {
  group('SetupPage', () {
    late SettingsViewModel settingsViewModel;
    late MockSettingsLocalDataSource mockDataSource;
    late MockAppLogger mockLogger;

    setUp(() {
      mockDataSource = MockSettingsLocalDataSource();
      mockLogger = MockAppLogger();
      settingsViewModel = SettingsViewModel(
        dataSource: mockDataSource,
        logger: mockLogger,
      );
    });

    Widget buildSetupPage() {
      final router = GoRouter(
        initialLocation: '/setup',
        routes: [
          GoRoute(
            path: '/setup',
            builder: (context, state) => const SetupPage(),
          ),
          GoRoute(
            path: '/onboarding',
            builder: (context, state) => const Scaffold(
              body: Center(child: Text('Onboarding Page')),
            ),
          ),
        ],
      );

      return ChangeNotifierProvider<SettingsViewModel>.value(
        value: settingsViewModel,
        child: MaterialApp.router(
          routerConfig: router,
          localizationsDelegates: const [
            AppLocalizations.delegate,
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          supportedLocales: const [
            Locale('en'),
            Locale('de'),
          ],
          locale: const Locale('en'),
        ),
      );
    }

    testWidgets('should display setup title', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.text('Welcome to Agenda Tasks'), findsOneWidget);
    });

    testWidgets('should display setup subtitle', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.text('Choose how you want to use the app'), findsOneWidget);
    });

    testWidgets('should display app icon', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.byIcon(Icons.task_alt), findsOneWidget);
    });

    testWidgets('should display local mode option', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.text('Use Locally'), findsOneWidget);
      expect(find.text('Keep tasks on this device only. No account needed.'), findsOneWidget);
      expect(find.byIcon(Icons.smartphone), findsOneWidget);
    });

    testWidgets('should display online mode option', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.text('Sync Online'), findsOneWidget);
      expect(find.text('Create an account to sync across devices.'), findsOneWidget);
      expect(find.byIcon(Icons.cloud_sync), findsOneWidget);
    });

    // Test ViewModel behavior directly since widget tests with navigation
    // cause timing issues with widget disposal
    test('ViewModel should set app mode to local correctly', () async {
      await settingsViewModel.setAppMode(AppMode.local);
      expect(settingsViewModel.appMode, AppMode.local);
    });

    test('ViewModel should set setup completed correctly', () async {
      await settingsViewModel.setSetupCompleted(true);
      expect(settingsViewModel.setupCompleted, true);
    });

    test('ViewModel should set app mode to online correctly', () async {
      await settingsViewModel.setAppMode(AppMode.online);
      expect(settingsViewModel.appMode, AppMode.online);
    });

    testWidgets('should have tappable local mode card', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      // Verify the InkWell is present and tappable
      final localCard = find.ancestor(
        of: find.text('Use Locally'),
        matching: find.byType(InkWell),
      );
      expect(localCard, findsOneWidget);
    });

    testWidgets('should have tappable online mode card', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      final onlineCard = find.ancestor(
        of: find.text('Sync Online'),
        matching: find.byType(InkWell),
      );
      expect(onlineCard, findsOneWidget);
    });

    testWidgets('should display two mode cards', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.byType(Card), findsNWidgets(2));
    });

    testWidgets('should have arrow icons on mode cards', (tester) async {
      await tester.pumpWidget(buildSetupPage());
      await tester.pumpAndSettle();

      expect(find.byIcon(Icons.arrow_forward_ios), findsNWidgets(2));
    });
  });
}
