import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:household_keeper/core/database/database.dart';
import 'package:household_keeper/core/router/router.dart';
import 'package:household_keeper/features/home/domain/calendar_models.dart';
import 'package:household_keeper/features/home/presentation/calendar_providers.dart';
import 'package:household_keeper/features/rooms/presentation/room_providers.dart';
import 'package:household_keeper/features/tasks/domain/effort_level.dart';
import 'package:household_keeper/features/tasks/domain/frequency.dart';
import 'package:household_keeper/features/tasks/domain/task_sort_option.dart';
import 'package:household_keeper/features/tasks/presentation/sort_preference_notifier.dart';
import 'package:household_keeper/l10n/app_localizations.dart';
import 'package:household_keeper/features/home/domain/daily_plan_models.dart';

/// Helper to create a test [Task] with sensible defaults.
Task _makeTask({
  int id = 1,
  int roomId = 1,
  String name = 'Test Task',
  required DateTime nextDueDate,
}) {
  return Task(
    id: id,
    roomId: roomId,
    name: name,
    intervalType: IntervalType.weekly,
    intervalDays: 7,
    effortLevel: EffortLevel.medium,
    nextDueDate: nextDueDate,
    createdAt: DateTime(2026, 1, 1),
    isActive: true,
  );
}

/// Helper to create a [TaskWithRoom].
TaskWithRoom _makeTaskWithRoom({
  int id = 1,
  int roomId = 1,
  String taskName = 'Test Task',
  String roomName = 'Kueche',
  required DateTime nextDueDate,
}) {
  return TaskWithRoom(
    task: _makeTask(
      id: id,
      roomId: roomId,
      name: taskName,
      nextDueDate: nextDueDate,
    ),
    roomName: roomName,
    roomId: roomId,
  );
}

/// Build the app with calendarDayProvider overridden to the given state.
///
/// Uses [UncontrolledProviderScope] with a [ProviderContainer] to avoid
/// the riverpod_lint scoped_providers_should_specify_dependencies warning.
Widget _buildApp(CalendarDayState dayState) {
  final container = ProviderContainer(overrides: [
    calendarDayProvider.overrideWith(
      (ref) => Stream.value(dayState),
    ),
    selectedDateProvider.overrideWith(SelectedDateNotifier.new),
    roomWithStatsListProvider.overrideWith(
      (ref) => Stream.value([]),
    ),
    sortPreferenceProvider.overrideWith(SortPreferenceNotifier.new),
  ]);

  return UncontrolledProviderScope(
    container: container,
    child: MaterialApp.router(
      routerConfig: router,
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: const [Locale('de')],
      locale: const Locale('de'),
    ),
  );
}

void main() {
  setUp(() {
    SharedPreferences.setMockInitialValues({});
  });

  final now = DateTime.now();
  final today = DateTime(now.year, now.month, now.day);
  final yesterday = today.subtract(const Duration(days: 1));

  group('HomeScreen empty states', () {
    testWidgets('shows no-tasks empty state when no tasks exist at all',
        (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: const [],
        overdueTasks: const [],
        totalTaskCount: 0,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // Should show "Noch keine Aufgaben angelegt" (dailyPlanNoTasks)
      expect(find.text('Noch keine Aufgaben angelegt'), findsOneWidget);
      // Should show action button to create a room
      expect(find.text('Raum erstellen'), findsOneWidget);
    });

    testWidgets('shows celebration state when tasks exist but today is clear',
        (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: const [],
        overdueTasks: const [],
        totalTaskCount: 5, // tasks exist elsewhere
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // Should show celebration state
      expect(find.byIcon(Icons.celebration_outlined), findsOneWidget);
      expect(find.text('Alles erledigt! \u{1F31F}'), findsOneWidget);
    });

    testWidgets('shows empty-day state for non-today date with no tasks',
        (tester) async {
      final tomorrow = today.add(const Duration(days: 1));
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: tomorrow,
        dayTasks: const [],
        overdueTasks: const [],
        totalTaskCount: 5, // tasks exist on other days
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // Should show "Keine Aufgaben" (not celebration — not today)
      expect(find.text('Keine Aufgaben'), findsOneWidget);
      expect(find.byIcon(Icons.event_available), findsOneWidget);
    });
  });

  group('HomeScreen normal state', () {
    testWidgets('shows overdue section when overdue tasks exist (today)',
        (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: [
          _makeTaskWithRoom(
            id: 2,
            taskName: 'Staubsaugen',
            roomName: 'Wohnzimmer',
            nextDueDate: today,
          ),
        ],
        overdueTasks: [
          _makeTaskWithRoom(
            id: 1,
            taskName: 'Boden wischen',
            roomName: 'Kueche',
            nextDueDate: yesterday,
          ),
        ],
        totalTaskCount: 2,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // Should show overdue section header
      expect(find.text('\u00dcberf\u00e4llig'), findsOneWidget);
      // Should show both tasks
      expect(find.text('Boden wischen'), findsOneWidget);
      expect(find.text('Staubsaugen'), findsOneWidget);
      // Should show room name tags
      expect(find.text('Kueche'), findsOneWidget);
      expect(find.text('Wohnzimmer'), findsOneWidget);
    });

    testWidgets('does not show overdue section for non-today date',
        (tester) async {
      // On a future date, overdueTasks will be empty (calendarDayProvider
      // only populates overdueTasks when isToday).
      final tomorrow = today.add(const Duration(days: 1));
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: tomorrow,
        dayTasks: [
          _makeTaskWithRoom(
            id: 1,
            taskName: 'Staubsaugen',
            roomName: 'Wohnzimmer',
            nextDueDate: tomorrow,
          ),
        ],
        overdueTasks: const [], // No overdue for non-today
        totalTaskCount: 1,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // Should NOT show overdue section header
      expect(find.text('\u00dcberf\u00e4llig'), findsNothing);
      // Should show day task
      expect(find.text('Staubsaugen'), findsOneWidget);
    });

    testWidgets('tasks have checkboxes', (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: [
          _makeTaskWithRoom(
            id: 1,
            taskName: 'Staubsaugen',
            roomName: 'Wohnzimmer',
            nextDueDate: today,
          ),
        ],
        overdueTasks: const [],
        totalTaskCount: 1,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // Task should have a checkbox
      expect(find.byType(Checkbox), findsOneWidget);
    });

    testWidgets('calendar strip is shown', (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: const [],
        overdueTasks: const [],
        totalTaskCount: 0,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // The strip is a horizontal ListView — verify it exists by finding
      // ListView widgets (strip + potentially the task list).
      expect(find.byType(ListView), findsWidgets);
    });
  });

  group('HomeScreen sort dropdown', () {
    testWidgets('shows sort dropdown in AppBar', (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: const [],
        overdueTasks: const [],
        totalTaskCount: 0,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // SortDropdown wraps a PopupMenuButton<TaskSortOption>
      expect(
        find.byType(PopupMenuButton<TaskSortOption>),
        findsOneWidget,
      );
    });

    testWidgets('shows AppBar with title', (tester) async {
      await tester.pumpWidget(_buildApp(CalendarDayState(
        selectedDate: today,
        dayTasks: const [],
        overdueTasks: const [],
        totalTaskCount: 0,
      )));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // tabHome l10n string is 'Übersicht'. It appears in the AppBar title
      // and also in the bottom navigation bar label — use findsWidgets.
      expect(find.text('\u00dcbersicht'), findsWidgets);
    });
  });
}
