import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:agenda_tasks/features/tasks/domain/entities/task_entity.dart';
import 'package:agenda_tasks/features/tasks/domain/enums/priority.dart';
import 'package:agenda_tasks/features/tasks/presentation/widgets/task_tile.dart';

import '../../../../helpers/test_helpers.dart';

void main() {
  group('TaskTile', () {
    late TaskEntity testTask;
    late bool toggleCalled;
    late bool tapCalled;
    late bool deleteCalled;
    late bool rescheduleCalled;

    setUp(() {
      toggleCalled = false;
      tapCalled = false;
      deleteCalled = false;
      rescheduleCalled = false;

      testTask = TaskEntity(
        id: 'test-task-1',
        title: 'Test Task Title',
        description: 'Test task description',
        date: DateTime(2026, 2, 3),
        priority: Priority.medium,
        isDone: false,
      );
    });

    Widget buildTaskTile({TaskEntity? task}) {
      return createTestableWidget(
        TaskTile(
          task: task ?? testTask,
          onToggle: () => toggleCalled = true,
          onTap: () => tapCalled = true,
          onDelete: () => deleteCalled = true,
          onReschedule: () => rescheduleCalled = true,
        ),
      );
    }

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

      expect(find.text('Test Task Title'), findsOneWidget);
    });

    testWidgets('should display task description', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      expect(find.text('Test task description'), findsOneWidget);
    });

    testWidgets('should not display description when null', (tester) async {
      final taskWithoutDesc = TaskEntity(
        id: 'test-task-2',
        title: 'Task Without Description',
        date: DateTime(2026, 2, 3),
      );

      await tester.pumpWidget(buildTaskTile(task: taskWithoutDesc));
      await tester.pumpAndSettle();

      expect(find.text('Task Without Description'), findsOneWidget);
      // Only title should be visible, no description text
    });

    testWidgets('should display checkbox unchecked when task is not done', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      final checkbox = tester.widget<Checkbox>(find.byType(Checkbox));
      expect(checkbox.value, false);
    });

    testWidgets('should display checkbox checked when task is done', (tester) async {
      final doneTask = testTask.copyWith(isDone: true);

      await tester.pumpWidget(buildTaskTile(task: doneTask));
      await tester.pumpAndSettle();

      final checkbox = tester.widget<Checkbox>(find.byType(Checkbox));
      expect(checkbox.value, true);
    });

    testWidgets('should call onToggle when checkbox is tapped', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      await tester.tap(find.byType(Checkbox));
      await tester.pumpAndSettle();

      expect(toggleCalled, true);
    });

    testWidgets('should call onTap when card is tapped', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      // Tap on the task title area (InkWell)
      await tester.tap(find.text('Test Task Title'));
      await tester.pumpAndSettle();

      expect(tapCalled, true);
    });

    testWidgets('should show popup menu when more button is tapped', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      // Find and tap the popup menu button
      await tester.tap(find.byType(PopupMenuButton<String>));
      await tester.pumpAndSettle();

      // Menu items should be visible
      expect(find.text('Move to tomorrow'), findsOneWidget);
      expect(find.text('Delete'), findsOneWidget);
    });

    testWidgets('should call onReschedule when reschedule menu item is tapped', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      // Open popup menu
      await tester.tap(find.byType(PopupMenuButton<String>));
      await tester.pumpAndSettle();

      // Tap reschedule option
      await tester.tap(find.text('Move to tomorrow'));
      await tester.pumpAndSettle();

      expect(rescheduleCalled, true);
    });

    testWidgets('should show delete confirmation dialog when delete menu item is tapped', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      // Open popup menu
      await tester.tap(find.byType(PopupMenuButton<String>));
      await tester.pumpAndSettle();

      // Tap delete option - find the one in the popup menu (second occurrence)
      final deleteTexts = find.text('Delete');
      await tester.tap(deleteTexts.last);
      await tester.pumpAndSettle();

      // Confirmation dialog should appear
      expect(find.text('Delete Task'), findsOneWidget);
      expect(find.text('Are you sure you want to delete this task?'), findsOneWidget);
    });

    testWidgets('should call onDelete when delete is confirmed', (tester) async {
      await tester.pumpWidget(buildTaskTile());
      await tester.pumpAndSettle();

      // Open popup menu
      await tester.tap(find.byType(PopupMenuButton<String>));
      await tester.pumpAndSettle();

      // Tap delete option in popup menu
      final deleteTexts = find.text('Delete');
      await tester.tap(deleteTexts.last);
      await tester.pumpAndSettle();

      // Dialog should be visible - find Delete button in dialog (the TextButton)
      final dialogDeleteButtons = find.widgetWithText(TextButton, 'Delete');
      await tester.tap(dialogDeleteButtons);
      await tester.pumpAndSettle();

      expect(deleteCalled, true);
    });

    testWidgets('should display strikethrough text when task is done', (tester) async {
      final doneTask = testTask.copyWith(isDone: true);

      await tester.pumpWidget(buildTaskTile(task: doneTask));
      await tester.pumpAndSettle();

      final titleFinder = find.text('Test Task Title');
      expect(titleFinder, findsOneWidget);

      final titleWidget = tester.widget<Text>(titleFinder);
      expect(titleWidget.style?.decoration, TextDecoration.lineThrough);
    });

    group('priority colors', () {
      testWidgets('should display red indicator for high priority', (tester) async {
        final highPriorityTask = testTask.copyWith(priority: Priority.high);

        await tester.pumpWidget(buildTaskTile(task: highPriorityTask));
        await tester.pumpAndSettle();

        // Find the priority indicator container
        final containers = tester.widgetList<Container>(find.byType(Container));
        final priorityIndicator = containers.where((c) {
          final decoration = c.decoration;
          if (decoration is BoxDecoration && c.constraints?.maxWidth == 5) {
            return decoration.color == Colors.red.shade700;
          }
          return false;
        });

        expect(priorityIndicator, isNotEmpty);
      });

      testWidgets('should display orange indicator for medium priority', (tester) async {
        final mediumPriorityTask = testTask.copyWith(priority: Priority.medium);

        await tester.pumpWidget(buildTaskTile(task: mediumPriorityTask));
        await tester.pumpAndSettle();

        final containers = tester.widgetList<Container>(find.byType(Container));
        final priorityIndicator = containers.where((c) {
          final decoration = c.decoration;
          if (decoration is BoxDecoration && c.constraints?.maxWidth == 5) {
            return decoration.color == Colors.orange.shade700;
          }
          return false;
        });

        expect(priorityIndicator, isNotEmpty);
      });

      testWidgets('should display green indicator for low priority', (tester) async {
        final lowPriorityTask = testTask.copyWith(priority: Priority.low);

        await tester.pumpWidget(buildTaskTile(task: lowPriorityTask));
        await tester.pumpAndSettle();

        final containers = tester.widgetList<Container>(find.byType(Container));
        final priorityIndicator = containers.where((c) {
          final decoration = c.decoration;
          if (decoration is BoxDecoration && c.constraints?.maxWidth == 5) {
            return decoration.color == Colors.green.shade700;
          }
          return false;
        });

        expect(priorityIndicator, isNotEmpty);
      });
    });
  });
}
