// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only

/// Tests app-level settings dialog behavior.
library;

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

import 'package:focus_flow_flutter/app/demo_scheduler_composition.dart';
import 'package:focus_flow_flutter/app/focus_flow_app.dart';

/// Runs app-level settings dialog tests.
void main() {
  testWidgets('sidebar Settings opens a dialog seeded with persisted values', (
    tester,
  ) async {
    await _pumpPlanApp(tester);

    await tester.tap(find.byKey(const ValueKey('nav-settings')));
    await tester.pumpAndSettle();

    expect(find.byType(AlertDialog), findsOneWidget);
    expect(find.text('UTC'), findsOneWidget);

    final compactSwitch = tester.widget<SwitchListTile>(
      find.byKey(const ValueKey('settings-compact-mode')),
    );
    expect(compactSwitch.value, isTrue);

    await tester.tap(find.text('Cancel'));
    await tester.pumpAndSettle();

    expect(find.byType(AlertDialog), findsNothing);
  });

  testWidgets('top bar Settings button opens the same dialog', (tester) async {
    await _pumpPlanApp(tester);

    await tester.tap(find.byKey(const ValueKey('top-bar-settings-button')));
    await tester.pumpAndSettle();

    expect(find.byKey(const ValueKey('settings-timezone')), findsOneWidget);

    await tester.tap(find.text('Cancel'));
    await tester.pumpAndSettle();
  });

  testWidgets('saving settings persists the change and reopens with it', (
    tester,
  ) async {
    await _pumpPlanApp(tester);

    await tester.tap(find.byKey(const ValueKey('nav-settings')));
    await tester.pumpAndSettle();

    await tester.tap(find.byKey(const ValueKey('settings-timezone')));
    await tester.pumpAndSettle();
    await tester.tap(find.text('EST').last);
    await tester.pumpAndSettle();

    await tester.tap(find.byKey(const ValueKey('settings-save')));
    await tester.pumpAndSettle();

    expect(find.byType(AlertDialog), findsNothing);

    await tester.tap(find.byKey(const ValueKey('nav-settings')));
    await tester.pumpAndSettle();

    expect(find.text('EST'), findsOneWidget);

    await tester.tap(find.text('Cancel'));
    await tester.pumpAndSettle();
  });

  testWidgets('invalid staleness thresholds show a calm inline error', (
    tester,
  ) async {
    await _pumpPlanApp(tester);

    await tester.tap(find.byKey(const ValueKey('nav-settings')));
    await tester.pumpAndSettle();

    await tester.enterText(
      find.byKey(const ValueKey('settings-aging-days')),
      '1',
    );
    await tester.pumpAndSettle();
    await tester.tap(find.byKey(const ValueKey('settings-save')));
    await tester.pumpAndSettle();

    expect(find.byType(AlertDialog), findsOneWidget);
    expect(
      find.text('Aging must be a number of days at least as large as Fresh.'),
      findsOneWidget,
    );

    await tester.tap(find.text('Cancel'));
    await tester.pumpAndSettle();
  });
}

/// Pumps the FocusFlow app at the desktop test size.
Future<void> _pumpPlanApp(WidgetTester tester) async {
  await tester.binding.setSurfaceSize(const Size(1586, 992));
  addTearDown(() => tester.binding.setSurfaceSize(null));
  await tester.pumpWidget(FocusFlowApp(composition: _composition()));
  await tester.pumpAndSettle();
}

/// Builds the seeded demo composition used by settings dialog tests.
DemoSchedulerComposition _composition() {
  return DemoSchedulerComposition.seeded(selectedDate: CivilDate(2025, 5, 20));
}
