import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:scheduler_core/scheduler_core.dart';

import 'package:focus_flow_flutter/controllers/scheduler_read_controller.dart';
import 'package:focus_flow_flutter/main.dart';
import 'package:focus_flow_flutter/widgets/backlog_pane.dart';

void main() {
  testWidgets('renders Today and Backlog read models', (tester) async {
    await tester.pumpWidget(
      FocusFlowApp(composition: DemoSchedulerComposition.seeded()),
    );
    await _pumpAndSettle(tester);

    expect(find.text('FocusFlow'), findsOneWidget);
    expect(find.text('Today'), findsWidgets);
    expect(find.text('Plan the day'), findsWidgets);
    expect(find.text('Appointment'), findsWidgets);

    await tester.tap(find.byIcon(Icons.inbox_outlined));
    await _pumpAndSettle(tester);

    expect(find.text('Backlog'), findsWidgets);
    expect(find.text('Send project update'), findsOneWidget);
    expect(find.text('Sort receipts'), findsOneWidget);
  });

  testWidgets('renders compact panel from owner settings', (tester) async {
    await tester.pumpWidget(
      FocusFlowApp(composition: DemoSchedulerComposition.seeded()),
    );
    await _pumpAndSettle(tester);

    expect(find.text('Compact'), findsOneWidget);
    expect(find.text('Plan the day'), findsNWidgets(2));
  });

  testWidgets('renders Backlog empty state', (tester) async {
    await tester.pumpWidget(
      _testShell(
        BacklogPane(
          controller: _FakeReadController<BacklogQueryResult>(
            SchedulerReadEmpty<BacklogQueryResult>(_emptyBacklog()),
          ),
        ),
      ),
    );

    expect(find.text('Backlog is clear'), findsOneWidget);
    expect(
      find.text('Captured tasks will appear here when they need planning.'),
      findsOneWidget,
    );
  });

  testWidgets('typed failure state can retry', (tester) async {
    final controller = _FakeReadController<BacklogQueryResult>(
      SchedulerReadFailure<BacklogQueryResult>(
        failure: const ApplicationFailure(
          code: ApplicationFailureCode.conflict,
        ),
      ),
      retryState: SchedulerReadEmpty<BacklogQueryResult>(_emptyBacklog()),
    );

    await tester.pumpWidget(_testShell(BacklogPane(controller: controller)));

    expect(find.text('Could not load Backlog'), findsOneWidget);
    expect(find.text('Status: conflict'), findsOneWidget);

    await tester.tap(find.text('Retry'));
    await _pumpAndSettle(tester);

    expect(controller.retryCount, 1);
    expect(find.text('Backlog is clear'), findsOneWidget);
  });

  testWidgets('quick capture schedules into Today and completes', (
    tester,
  ) async {
    final composition = DemoSchedulerComposition.seeded(
      includeTodayItems: false,
      includeBacklogItems: false,
    );

    await tester.pumpWidget(FocusFlowApp(composition: composition));
    await _pumpAndSettle(tester);

    await tester.tap(find.byIcon(Icons.inbox_outlined));
    await _pumpAndSettle(tester);

    await tester.enterText(
      find.byKey(const ValueKey('quick-capture-title')),
      'Water plants',
    );
    await tester.tap(find.text('Capture'));
    await _pumpAndSettle(tester);

    expect(find.text('Water plants'), findsOneWidget);
    expect(composition.store.currentTasks.single.status, TaskStatus.backlog);

    await tester.enterText(find.byType(TextField).last, '20');
    await tester.tap(find.byTooltip('Schedule'));
    await _pumpAndSettle(tester);

    await tester.tap(find.byIcon(Icons.today_outlined));
    await _pumpAndSettle(tester);

    expect(find.text('Water plants'), findsWidgets);
    expect(composition.store.currentTasks.single.status, TaskStatus.planned);

    await tester.tap(find.byTooltip('Done').first);
    await _pumpAndSettle(tester);

    expect(composition.store.currentTasks.single.status, TaskStatus.completed);
  });
}

Future<int> _pumpAndSettle(WidgetTester tester) {
  return tester.pumpAndSettle(
    const Duration(milliseconds: 50),
    EnginePhase.sendSemanticsUpdate,
    const Duration(seconds: 2),
  );
}

Widget _testShell(Widget child) {
  return MaterialApp(
    theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: const Color(0xFF2F6F73),
        brightness: Brightness.dark,
      ),
      useMaterial3: true,
    ),
    home: Scaffold(body: child),
  );
}

BacklogQueryResult _emptyBacklog() {
  return BacklogQueryResult(
    ownerId: 'owner-1',
    settings: OwnerSettings(ownerId: 'owner-1', timeZoneId: 'UTC'),
    items: const [],
  );
}

class _FakeReadController<T> extends UiReadController<T> {
  _FakeReadController(SchedulerReadState<T> state, {this.retryState})
    : _state = state;

  SchedulerReadState<T> _state;
  final SchedulerReadState<T>? retryState;
  int retryCount = 0;

  @override
  SchedulerReadState<T> get state => _state;

  @override
  Future<void> load() async {}

  @override
  Future<void> retry() async {
    retryCount += 1;
    final next = retryState;
    if (next != null) {
      _state = next;
      notifyListeners();
    }
  }
}
