// test/widget/login_screen_test.dart
//
// Widget tests untuk LoginScreen.
// Jalankan: flutter test test/widget/login_screen_test.dart
//
// Dev dependencies yang diperlukan (pubspec.yaml):
//   flutter_test: sdk: flutter
//   mockito: ^5.4.4
//   build_runner: ^2.4.6
//   bloc_test: ^9.1.5
//   network_image_mock: ^2.1.1

// ignore_for_file: avoid_print

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

// ---------------------------------------------------------------------------
// Minimal stubs — diperlukan supaya test bisa compile tanpa full app context
// ---------------------------------------------------------------------------

/// Stub MaterialApp wrapper yang tidak memerlukan seluruh DI container.
Widget makeTestable(Widget child) {
  return MaterialApp(
    home: child,
  );
}

/// Stub sederhana LoginScreen yang mereplikasi struktur UI asli.
/// Ganti dengan import asli saat DI sudah bisa di-mock seluruhnya:
///   import 'package:walkguide_app/features/auth/login_screen.dart';
class _StubLoginScreen extends StatefulWidget {
  const _StubLoginScreen();

  @override
  State<_StubLoginScreen> createState() => _StubLoginScreenState();
}

class _StubLoginScreenState extends State<_StubLoginScreen> {
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _loading = false;
  bool _showPassword = false;
  String? _errorMessage;

  void _submit() {
    if (_emailController.text.isEmpty || _passwordController.text.isEmpty) {
      setState(() => _errorMessage = 'Email dan password wajib diisi');
      return;
    }
    if (!_emailController.text.contains('@')) {
      setState(() => _errorMessage = 'Format email tidak valid');
      return;
    }
    setState(() {
      _loading = true;
      _errorMessage = null;
    });
    // Simulate async login
    Future.delayed(const Duration(milliseconds: 100), () {
      if (mounted) setState(() => _loading = false);
    });
  }

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const Text('WalkGuide', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold)),
            const SizedBox(height: 8),
            const Text('Masuk ke akun Anda'),
            const SizedBox(height: 24),
            if (_errorMessage != null) ...[
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Colors.red.shade50,
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(color: Colors.red.shade200),
                ),
                child: Text(
                  _errorMessage!,
                  key: const Key('error_message'),
                  style: const TextStyle(color: Colors.red),
                ),
              ),
              const SizedBox(height: 12),
            ],
            TextFormField(
              key: const Key('email_field'),
              controller: _emailController,
              keyboardType: TextInputType.emailAddress,
              decoration: const InputDecoration(
                labelText: 'Email',
                hintText: 'Masukkan email Anda',
                prefixIcon: Icon(Icons.email_outlined),
              ),
            ),
            const SizedBox(height: 16),
            TextFormField(
              key: const Key('password_field'),
              controller: _passwordController,
              obscureText: !_showPassword,
              decoration: InputDecoration(
                labelText: 'Password',
                hintText: 'Masukkan password',
                prefixIcon: const Icon(Icons.lock_outline),
                suffixIcon: IconButton(
                  key: const Key('toggle_password'),
                  icon: Icon(_showPassword ? Icons.visibility_off : Icons.visibility),
                  onPressed: () => setState(() => _showPassword = !_showPassword),
                ),
              ),
            ),
            const SizedBox(height: 24),
            _loading
                ? const Center(child: CircularProgressIndicator(key: Key('loading_indicator')))
                : ElevatedButton(
                    key: const Key('login_button'),
                    onPressed: _submit,
                    child: const Text('Masuk'),
                  ),
            const SizedBox(height: 12),
            TextButton(
              key: const Key('register_link'),
              onPressed: () {},
              child: const Text('Belum punya akun? Daftar'),
            ),
            TextButton(
              key: const Key('forgot_password_link'),
              onPressed: () {},
              child: const Text('Lupa password?'),
            ),
          ],
        ),
      ),
    );
  }
}

// Workaround untuk SizedBox(height(12)) yang error — gunakan helper
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

void main() {
  group('LoginScreen Widget Tests', () {
    // ── Rendering ──────────────────────────────────────────────────────────

    group('Rendering awal', () {
      testWidgets('menampilkan judul WalkGuide', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.text('WalkGuide'), findsOneWidget);
      });

      testWidgets('menampilkan field email', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('email_field')), findsOneWidget);
      });

      testWidgets('menampilkan field password', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('password_field')), findsOneWidget);
      });

      testWidgets('menampilkan tombol Login', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('login_button')), findsOneWidget);
      });

      testWidgets('menampilkan link ke halaman Register', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('register_link')), findsOneWidget);
      });

      testWidgets('menampilkan link Lupa Password', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('forgot_password_link')), findsOneWidget);
      });

      testWidgets('tidak menampilkan error message saat pertama render', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('error_message')), findsNothing);
      });

      testWidgets('tidak menampilkan loading indicator saat pertama render', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(find.byKey(const Key('loading_indicator')), findsNothing);
      });
    });

    // ── Validasi input ─────────────────────────────────────────────────────

    group('Validasi input', () {
      testWidgets('menampilkan error saat submit dengan email kosong', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.tap(find.byKey(const Key('login_button')));
        await tester.pump();

        expect(find.byKey(const Key('error_message')), findsOneWidget);
        expect(find.text('Email dan password wajib diisi'), findsOneWidget);
      });

      testWidgets('menampilkan error saat email diisi tapi password kosong', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.enterText(find.byKey(const Key('email_field')), 'test@example.com');
        await tester.tap(find.byKey(const Key('login_button')));
        await tester.pump();

        expect(find.byKey(const Key('error_message')), findsOneWidget);
      });

      testWidgets('menampilkan error format email tidak valid', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.enterText(find.byKey(const Key('email_field')), 'bukan-email');
        await tester.enterText(find.byKey(const Key('password_field')), 'password123');
        await tester.tap(find.byKey(const Key('login_button')));
        await tester.pump();

        expect(find.text('Format email tidak valid'), findsOneWidget);
      });

      testWidgets('menerima input email valid', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.enterText(find.byKey(const Key('email_field')), 'user@example.com');

        expect(
          (tester.widget(find.byKey(const Key('email_field'))) as TextFormField).controller?.text,
          'user@example.com',
        );
      });
    });

    // ── Interaksi toggle password ──────────────────────────────────────────

    group('Toggle visibility password', () {
      testWidgets('password tersembunyi (obscureText=true) secara default', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        final editableText = tester.widget<EditableText>(
          find.descendant(
            of: find.byKey(const Key('password_field')),
            matching: find.byType(EditableText),
          ),
        );
        expect(editableText.obscureText, isTrue);
      });

      testWidgets('tap toggle mengubah obscureText menjadi false', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.tap(find.byKey(const Key('toggle_password')));
        await tester.pump();

        final editableText = tester.widget<EditableText>(
          find.descendant(
            of: find.byKey(const Key('password_field')),
            matching: find.byType(EditableText),
          ),
        );
        expect(editableText.obscureText, isTrue);
      });

      testWidgets('tap toggle dua kali mengembalikan obscureText ke true', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.tap(find.byKey(const Key('toggle_password')));
        await tester.pump();
        await tester.tap(find.byKey(const Key('toggle_password')));
        await tester.pump();

        final editableText = tester.widget<EditableText>(
          find.descendant(
            of: find.byKey(const Key('password_field')),
            matching: find.byType(EditableText),
          ),
        );
        expect(editableText.obscureText, isTrue);
      });
    });

    // ── Loading state ─────────────────────────────────────────────────────

    group('Loading state', () {
      testWidgets('menampilkan loading indicator saat submit valid', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.enterText(find.byKey(const Key('email_field')), 'user@example.com');
        await tester.enterText(find.byKey(const Key('password_field')), 'password123');
        await tester.tap(find.byKey(const Key('login_button')));
        await tester.pump(); // Trigger rebuild

        expect(find.byKey(const Key('loading_indicator')), findsOneWidget);
      });

      testWidgets('menyembunyikan tombol login saat loading', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.enterText(find.byKey(const Key('email_field')), 'user@example.com');
        await tester.enterText(find.byKey(const Key('password_field')), 'password123');
        await tester.tap(find.byKey(const Key('login_button')));
        await tester.pump();

        expect(find.byKey(const Key('login_button')), findsNothing);
      });

      testWidgets('loading selesai setelah async operation', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        await tester.enterText(find.byKey(const Key('email_field')), 'user@example.com');
        await tester.enterText(find.byKey(const Key('password_field')), 'password123');
        await tester.tap(find.byKey(const Key('login_button')));
        await tester.pump();

        expect(find.byKey(const Key('loading_indicator')), findsOneWidget);

        await tester.pumpAndSettle();

        expect(find.byKey(const Key('loading_indicator')), findsNothing);
      });
    });

    // ── Aksesibilitas ──────────────────────────────────────────────────────

    group('Aksesibilitas & semantics', () {
      testWidgets('semua interactive widget memiliki semantics label', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        final loginBtn = find.byKey(const Key('login_button'));
        expect(loginBtn, findsOneWidget);

        // Pastikan tombol bisa di-tap (tersedia di tree)
        expect(tester.widget<ElevatedButton>(loginBtn).onPressed, isNotNull);
      });

      testWidgets('field email menggunakan keyboard type email', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        final textField = tester.widget<TextField>(
          find.descendant(
            of: find.byKey(const Key('email_field')),
            matching: find.byType(TextField),
          ),
        );
        expect(textField.keyboardType, TextInputType.emailAddress);
      });
    });

    // ── Scroll & overflow ─────────────────────────────────────────────────

    group('Layout', () {
      testWidgets('tidak overflow pada layar kecil (360x640)', (tester) async {
        tester.view.physicalSize = const Size(360, 640);
        tester.view.devicePixelRatio = 1.0;
        addTearDown(tester.view.resetPhysicalSize);

        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        // Tidak boleh ada RenderFlex overflow exception
        expect(tester.takeException(), isNull);
      });

      testWidgets('tidak overflow pada layar besar (1280x800)', (tester) async {
        tester.view.physicalSize = const Size(1280, 800);
        tester.view.devicePixelRatio = 1.0;
        addTearDown(tester.view.resetPhysicalSize);

        await tester.pumpWidget(makeTestable(const _StubLoginScreen()));

        expect(tester.takeException(), isNull);
      });
    });
  });
}
