// integration_test/flow_3_notification_read_all_test.dart
//
// E2E Flow 3: Login → Notifikasi → Tandai Semua Dibaca → Kembali
//
// Alur yang diuji:
//   1. Login berhasil → Dashboard
//   2. Tap ikon notifikasi / tombol "Buka Notifikasi" → NotificationScreen
//   3. Unread badge count ditampilkan dengan benar
//   4. Tap "Tandai Semua Dibaca" → semua notifikasi berubah menjadi dibaca
//   5. Unread badge menjadi 0
//   6. Tap kembali → kembali ke Dashboard
//   7. Badge di Dashboard juga ter-update menjadi 0
//
// Jalankan:
//   flutter test integration_test/flow_3_notification_read_all_test.dart

// ignore_for_file: avoid_print

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

// ─── Fake Credentials ────────────────────────────────────────────────────────

const _kEmail = 'user@walkguide.test';
const _kPassword = 'Password123!';

// ─── Data Models ─────────────────────────────────────────────────────────────

class _Notification {
  final int id;
  final String content;
  final String sender;
  bool isRead;

  _Notification({
    required this.id,
    required this.content,
    required this.sender,
    this.isRead = false,
  });
}

// ─── Stub State ──────────────────────────────────────────────────────────────

class _AppState extends ChangeNotifier {
  bool _loggedIn = false;
  String _screen = 'login'; // login | dashboard | notification

  final List<_Notification> _notifications = [
    _Notification(
        id: 1,
        content: 'Hati-hati di persimpangan Jalan A',
        sender: 'Guardian Pak Budi'),
    _Notification(
        id: 2,
        content: 'Cuaca memburuk, segera pulang',
        sender: 'Guardian Pak Budi'),
    _Notification(
        id: 3,
        content: 'WalkGuide kamu sudah berjalan 2 jam',
        sender: 'Sistem'),
    _Notification(
        id: 4,
        content: 'Ini notifikasi yang sudah dibaca',
        sender: 'Sistem',
        isRead: true),
  ];

  bool get loggedIn => _loggedIn;
  String get screen => _screen;
  List<_Notification> get notifications => List.unmodifiable(_notifications);
  int get unreadCount => _notifications.where((n) => !n.isRead).length;

  Future<bool> login(String email, String password) async {
    await Future.delayed(const Duration(milliseconds: 150));
    if (email == _kEmail && password == _kPassword) {
      _loggedIn = true;
      _screen = 'dashboard';
      notifyListeners();
      return true;
    }
    return false;
  }

  void openNotifications() {
    _screen = 'notification';
    notifyListeners();
  }

  void goToDashboard() {
    _screen = 'dashboard';
    notifyListeners();
  }

  void markAsRead(int id) {
    final n = _notifications.firstWhere((n) => n.id == id);
    if (!n.isRead) {
      n.isRead = true;
      notifyListeners();
    }
  }

  Future<void> markAllAsRead() async {
    await Future.delayed(const Duration(milliseconds: 150));
    for (final n in _notifications) {
      n.isRead = true;
    }
    notifyListeners();
  }
}

// ─── Stub App ─────────────────────────────────────────────────────────────────

class _StubApp extends StatefulWidget {
  const _StubApp();

  @override
  State<_StubApp> createState() => _StubAppState();
}

class _StubAppState extends State<_StubApp> {
  final _state = _AppState();

  @override
  void dispose() {
    _state.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WalkGuide Test',
      home: ListenableBuilder(
        listenable: _state,
        builder: (context, _) {
          switch (_state.screen) {
            case 'notification':
              return _NotificationScreen(state: _state);
            case 'dashboard':
              return _DashboardScreen(state: _state);
            default:
              return _LoginScreen(state: _state);
          }
        },
      ),
    );
  }
}

// ─── Login Screen ─────────────────────────────────────────────────────────────

class _LoginScreen extends StatefulWidget {
  final _AppState state;
  const _LoginScreen({required this.state});

  @override
  State<_LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<_LoginScreen> {
  final _emailCtrl = TextEditingController();
  final _passwordCtrl = TextEditingController();
  bool _loading = false;

  @override
  void dispose() {
    _emailCtrl.dispose();
    _passwordCtrl.dispose();
    super.dispose();
  }

  Future<void> _submit() async {
    setState(() => _loading = true);
    await widget.state.login(_emailCtrl.text.trim(), _passwordCtrl.text.trim());
    if (mounted) setState(() => _loading = false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(children: [
          TextField(
            key: const Key('emailField'),
            controller: _emailCtrl,
            decoration: const InputDecoration(labelText: 'Email'),
          ),
          const SizedBox(height: 12),
          TextField(
            key: const Key('passwordField'),
            controller: _passwordCtrl,
            obscureText: true,
            decoration: const InputDecoration(labelText: 'Password'),
          ),
          const SizedBox(height: 24),
          if (_loading)
            const CircularProgressIndicator()
          else
            ElevatedButton(
              key: const Key('loginButton'),
              onPressed: _submit,
              child: const Text('Login'),
            ),
        ]),
      ),
    );
  }
}

// ─── Dashboard Screen ─────────────────────────────────────────────────────────

class _DashboardScreen extends StatelessWidget {
  final _AppState state;
  const _DashboardScreen({required this.state});

  @override
  Widget build(BuildContext context) {
    final unread = state.unreadCount;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dashboard'),
        actions: [
          Stack(
            alignment: Alignment.topRight,
            children: [
              IconButton(
                key: const Key('notifIconButton'),
                icon: const Icon(Icons.notifications),
                tooltip: 'Notifikasi',
                onPressed: state.openNotifications,
              ),
              if (unread > 0)
                Positioned(
                  right: 8,
                  top: 8,
                  child: Container(
                    key: const Key('dashboardBadge'),
                    padding: const EdgeInsets.all(4),
                    decoration: const BoxDecoration(
                      color: Colors.red,
                      shape: BoxShape.circle,
                    ),
                    child: Text(
                      '$unread',
                      style: const TextStyle(color: Colors.white, fontSize: 10),
                    ),
                  ),
                ),
            ],
          ),
        ],
      ),
      body: Center(
        child: Column(mainAxisSize: MainAxisSize.min, children: [
          const Text('Selamat datang di Dashboard'),
          const SizedBox(height: 16),
          ElevatedButton(
            key: const Key('openNotifButton'),
            onPressed: state.openNotifications,
            child: Text(
              unread > 0
                  ? 'Lihat Notifikasi ($unread belum dibaca)'
                  : 'Lihat Notifikasi',
            ),
          ),
        ]),
      ),
    );
  }
}

// ─── Notification Screen ──────────────────────────────────────────────────────

class _NotificationScreen extends StatelessWidget {
  final _AppState state;
  const _NotificationScreen({required this.state});

  @override
  Widget build(BuildContext context) {
    final notifs = state.notifications;
    final unread = state.unreadCount;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Notifikasi'),
        leading: IconButton(
          key: const Key('notifBackButton'),
          icon: const Icon(Icons.arrow_back),
          onPressed: state.goToDashboard,
        ),
        actions: [
          if (unread > 0)
            TextButton(
              key: const Key('markAllReadButton'),
              onPressed: state.markAllAsRead,
              child: const Text(
                'Tandai Semua Dibaca',
                style: TextStyle(color: Colors.white),
              ),
            ),
        ],
      ),
      body: Column(children: [
        // Unread count info
        Padding(
          padding: const EdgeInsets.all(16),
          child: Row(children: [
            Text(
              '$unread notifikasi belum dibaca',
              key: const Key('unreadCountLabel'),
              style: const TextStyle(fontWeight: FontWeight.bold),
            ),
            if (unread == 0)
              const Padding(
                padding: EdgeInsets.only(left: 8),
                child: Icon(Icons.check_circle, color: Colors.green, size: 18),
              ),
          ]),
        ),
        const Divider(height: 1),

        // Notification list
        Expanded(
          child: ListView.builder(
            key: const Key('notifList'),
            itemCount: notifs.length,
            itemBuilder: (_, i) {
              final n = notifs[i];
              return ListTile(
                key: Key('notifItem_${n.id}'),
                leading: Icon(
                  n.isRead ? Icons.mark_email_read : Icons.email,
                  color: n.isRead ? Colors.grey : Colors.blue,
                ),
                title: Text(n.content),
                subtitle: Text('Dari: ${n.sender}'),
                tileColor: n.isRead ? null : Colors.blue.shade50,
                trailing: n.isRead
                    ? const Text('Dibaca',
                        key: Key('readLabel'),
                        style: TextStyle(color: Colors.grey, fontSize: 12))
                    : TextButton(
                        onPressed: () => state.markAsRead(n.id),
                        child: const Text('Tandai Dibaca'),
                      ),
              );
            },
          ),
        ),
      ]),
    );
  }
}

// ─── Tests ────────────────────────────────────────────────────────────────────

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('Flow 3 — Login → Notifikasi → Tandai Semua Dibaca → Kembali', () {
    /// Helper: login
    Future<void> loginAndGoToDashboard(WidgetTester tester) async {
      await tester.pumpWidget(const _StubApp());
      await tester.pumpAndSettle();

      await tester.enterText(find.byKey(const Key('emailField')), _kEmail);
      await tester.enterText(
          find.byKey(const Key('passwordField')), _kPassword);
      await tester.tap(find.byKey(const Key('loginButton')));
      await tester.pumpAndSettle();
    }

    testWidgets(
      '3.1  Dashboard menampilkan badge jumlah notifikasi belum dibaca',
      (tester) async {
        await loginAndGoToDashboard(tester);

        expect(find.text('Dashboard'), findsOneWidget);
        // Ada 3 notifikasi unread (id 1, 2, 3); id 4 sudah read
        expect(find.byKey(const Key('dashboardBadge')), findsOneWidget,
            reason: 'Badge harus muncul karena ada notif belum dibaca');
        expect(find.text('3'), findsOneWidget,
            reason: 'Badge harus menampilkan angka 3');

        print(
            '[PASS] 3.1  Dashboard badge menampilkan jumlah unread yang benar');
      },
    );

    testWidgets(
      '3.2  Tap ikon notifikasi → NotificationScreen terbuka dengan daftar notif',
      (tester) async {
        await loginAndGoToDashboard(tester);

        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();

        expect(find.text('Notifikasi'), findsOneWidget,
            reason: 'Harus masuk ke NotificationScreen');
        expect(find.byKey(const Key('notifList')), findsOneWidget,
            reason: 'ListView notifikasi harus tampil');

        // 4 notifikasi harus tampil
        expect(find.byKey(const Key('notifItem_1')), findsOneWidget);
        expect(find.byKey(const Key('notifItem_2')), findsOneWidget);
        expect(find.byKey(const Key('notifItem_3')), findsOneWidget);
        expect(find.byKey(const Key('notifItem_4')), findsOneWidget);

        print('[PASS] 3.2  NotificationScreen terbuka dengan semua notifikasi');
      },
    );

    testWidgets(
      '3.3  Label unread count tampil dengan angka yang benar di NotificationScreen',
      (tester) async {
        await loginAndGoToDashboard(tester);

        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();

        expect(find.byKey(const Key('unreadCountLabel')), findsOneWidget);
        expect(find.text('3 notifikasi belum dibaca'), findsOneWidget,
            reason: 'Harus menampilkan "3 notifikasi belum dibaca"');

        print('[PASS] 3.3  Unread count label menampilkan angka yang benar');
      },
    );

    testWidgets(
      '3.4  Tombol "Tandai Semua Dibaca" muncul saat ada notif belum dibaca',
      (tester) async {
        await loginAndGoToDashboard(tester);

        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();

        expect(find.byKey(const Key('markAllReadButton')), findsOneWidget,
            reason: 'Tombol "Tandai Semua Dibaca" harus tampil');

        print('[PASS] 3.4  Tombol "Tandai Semua Dibaca" tampil');
      },
    );

    testWidgets(
      '3.5  Tap "Tandai Semua Dibaca" → semua notif jadi dibaca, count jadi 0',
      (tester) async {
        await loginAndGoToDashboard(tester);

        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();

        // Sebelum: 3 unread
        expect(find.text('3 notifikasi belum dibaca'), findsOneWidget);

        await tester.tap(find.byKey(const Key('markAllReadButton')));
        await tester.pumpAndSettle();

        // Setelah: 0 unread
        expect(find.text('0 notifikasi belum dibaca'), findsOneWidget,
            reason: 'Setelah tandai semua, count harus 0');
        expect(find.byKey(const Key('markAllReadButton')), findsNothing,
            reason: 'Tombol "Tandai Semua" harus hilang saat tidak ada unread');

        print('[PASS] 3.5  Tandai semua dibaca → count menjadi 0');
      },
    );

    testWidgets(
      '3.6  Tandai satu notif dibaca → count berkurang 1',
      (tester) async {
        await loginAndGoToDashboard(tester);

        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();

        expect(find.text('3 notifikasi belum dibaca'), findsOneWidget);

        // Scroll ke notif pertama yang unread dan tandai
        final markButtons = find.text('Tandai Dibaca');
        expect(markButtons, findsWidgets);
        await tester.tap(markButtons.first);
        await tester.pumpAndSettle();

        expect(find.text('2 notifikasi belum dibaca'), findsOneWidget,
            reason: 'Count harus berkurang menjadi 2');

        print('[PASS] 3.6  Tandai satu notif → count berkurang 1');
      },
    );

    testWidgets(
      '3.7  Kembali ke Dashboard → badge ter-update menjadi 0 setelah tandai semua',
      (tester) async {
        await loginAndGoToDashboard(tester);

        // Buka notifikasi
        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();

        // Tandai semua dibaca
        await tester.tap(find.byKey(const Key('markAllReadButton')));
        await tester.pumpAndSettle();

        // Kembali ke dashboard
        await tester.tap(find.byKey(const Key('notifBackButton')));
        await tester.pumpAndSettle();

        expect(find.text('Dashboard'), findsOneWidget,
            reason: 'Harus kembali ke Dashboard');
        expect(find.byKey(const Key('dashboardBadge')), findsNothing,
            reason: 'Badge harus hilang karena semua sudah dibaca');
        expect(find.text('Lihat Notifikasi'), findsOneWidget,
            reason: 'Tombol notifikasi harus tanpa keterangan "belum dibaca"');

        print('[PASS] 3.7  Kembali ke Dashboard → badge hilang');
      },
    );

    testWidgets(
      '3.8  Buka notifikasi via tombol di body Dashboard juga berfungsi',
      (tester) async {
        await loginAndGoToDashboard(tester);

        await tester.tap(find.byKey(const Key('openNotifButton')));
        await tester.pumpAndSettle();

        expect(find.text('Notifikasi'), findsOneWidget,
            reason:
                'Tombol di body Dashboard juga harus membuka NotificationScreen');

        print('[PASS] 3.8  Tombol notif di body Dashboard berfungsi');
      },
    );

    testWidgets(
      '3.9  Full round-trip: Login → Notif → Tandai Semua → Kembali → Badge = 0',
      (tester) async {
        await loginAndGoToDashboard(tester);

        // Verify badge ada
        expect(find.byKey(const Key('dashboardBadge')), findsOneWidget);

        // Buka notifikasi
        await tester.tap(find.byKey(const Key('notifIconButton')));
        await tester.pumpAndSettle();
        expect(find.text('Notifikasi'), findsOneWidget);

        // Tandai semua
        await tester.tap(find.byKey(const Key('markAllReadButton')));
        await tester.pumpAndSettle();
        expect(find.text('0 notifikasi belum dibaca'), findsOneWidget);

        // Kembali
        await tester.tap(find.byKey(const Key('notifBackButton')));
        await tester.pumpAndSettle();
        expect(find.text('Dashboard'), findsOneWidget);
        expect(find.byKey(const Key('dashboardBadge')), findsNothing,
            reason: 'Setelah semua dibaca, badge harus hilang dari Dashboard');

        print('[PASS] 3.9  Full round-trip notifikasi berhasil');
      },
    );
  });
}
