// test/widget/walk_guide_screen_test.dart
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables
//
// Widget tests untuk WalkGuideScreen — layar utama navigasi tunanetra.
// Jalankan: flutter test test/widget/walk_guide_screen_test.dart
//
// Dev dependencies:
//   flutter_test: sdk: flutter
//   mockito: ^5.4.4
//   build_runner: ^2.4.6

// ignore_for_file: avoid_print

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

// ---------------------------------------------------------------------------
// Stubs / Models
// ---------------------------------------------------------------------------

/// Mereplikasi DetectionResult dari core/ai/obstacle_analyzer.dart
class DetectionResult {
  final String label;
  final double confidence;
  final String direction;  // 'LEFT' | 'CENTER' | 'RIGHT'
  final String distance;   // 'Very Close' | 'Close' | 'Medium' | 'Far'
  final bool isAlert;

  const DetectionResult({
    required this.label,
    required this.confidence,
    required this.direction,
    required this.distance,
    required this.isAlert,
  });
}

/// Stub WalkGuideScreen yang meniru UI asli tanpa plugin dependencies
class _StubWalkGuideScreen extends StatefulWidget {
  final DetectionResult? initialDetection;
  final bool initialActive;
  final bool cameraError;

  const _StubWalkGuideScreen({
    this.initialDetection,
    this.initialActive = false,
    this.cameraError = false,
  });

  @override
  State<_StubWalkGuideScreen> createState() => _StubWalkGuideScreenState();
}

class _StubWalkGuideScreenState extends State<_StubWalkGuideScreen> {
  late bool _active;
  late String _status;
  DetectionResult? _lastDetection;
  bool _hasCameraError = false;

  @override
  void initState() {
    super.initState();
    _active = widget.initialActive;
    _status = widget.initialActive ? 'Active' : 'Ready';
    _lastDetection = widget.initialDetection;
    _hasCameraError = widget.cameraError;
  }

  void _toggleActive() {
    setState(() {
      _active = !_active;
      _status = _active ? 'Active' : 'Ready';
      if (!_active) _lastDetection = null;
    });
  }

  Color get _statusColor {
    if (!_active) return Colors.grey;
    if (_lastDetection == null) return Colors.green;
    if (_lastDetection!.isAlert) return Colors.red;
    return Colors.orange;
  }

  String get _directionEmoji {
    if (_lastDetection == null) return '';
    return switch (_lastDetection!.direction) {
      'LEFT' => '⬅️',
      'RIGHT' => '➡️',
      _ => '⬆️',
    };
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('WalkGuide'),
        actions: [
          IconButton(
            key: const Key('settings_button'),
            icon: const Icon(Icons.settings),
            onPressed: () {},
          ),
        ],
      ),
      body: Column(
        children: [
          // Status bar
          Container(
            key: const Key('status_bar'),
            width: double.infinity,
            padding: const EdgeInsets.all(16),
            color: _statusColor,
            child: Text(
              key: const Key('status_text'),
              _status,
              style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
              textAlign: TextAlign.center,
            ),
          ),

          // Camera preview area
          Expanded(
            child: _hasCameraError
                ? Center(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        const Icon(Icons.camera_alt, size: 64, color: Colors.grey,
                            key: Key('camera_error_icon')),
                        const SizedBox(height: 8),
                        const Text(
                          key: Key('camera_error_text'),
                          'Kamera tidak tersedia',
                          style: TextStyle(color: Colors.grey),
                        ),
                      ],
                    ),
                  )
                : Container(
                    key: const Key('camera_preview'),
                    color: Colors.black,
                    child: _active
                        ? Stack(
                            children: [
                              const Center(
                                child: Text(
                                  'Camera Preview',
                                  style: TextStyle(color: Colors.white38),
                                ),
                              ),
                              if (_lastDetection != null)
                                Positioned(
                                  bottom: 16,
                                  left: 0,
                                  right: 0,
                                  child: _DetectionOverlay(detection: _lastDetection!),
                                ),
                            ],
                          )
                        : const Center(
                            child: Text(
                              'Tekan Start untuk memulai',
                              key: Key('inactive_hint'),
                              style: TextStyle(color: Colors.white54),
                            ),
                          ),
                  ),
          ),

          // Bottom controls
          Padding(
            padding: const EdgeInsets.all(20),
            child: Column(
              children: [
                // Detection info card
                if (_lastDetection != null)
                  Card(
                    key: const Key('detection_card'),
                    child: Padding(
                      padding: const EdgeInsets.all(12),
                      child: Row(
                        children: [
                          Text(
                            _directionEmoji,
                            key: const Key('direction_emoji'),
                            style: const TextStyle(fontSize: 24),
                          ),
                          const SizedBox(width: 12),
                          Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  key: const Key('detection_label'),
                                  _lastDetection!.label,
                                  style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                                ),
                                Text(
                                  key: const Key('detection_distance'),
                                  _lastDetection!.distance,
                                  style: TextStyle(color: Colors.grey.shade600),
                                ),
                              ],
                            ),
                          ),
                          Text(
                            key: const Key('detection_confidence'),
                            '${(_lastDetection!.confidence * 100).toStringAsFixed(0)}%',
                            style: const TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ],
                      ),
                    ),
                  ),

                const SizedBox(height: 12),

                // Start/Stop button
                SizedBox(
                  width: double.infinity,
                  height: 56,
                  child: ElevatedButton.icon(
                    key: const Key('toggle_button'),
                    onPressed: _hasCameraError ? null : _toggleActive,
                    icon: Icon(_active ? Icons.stop : Icons.play_arrow),
                    label: Text(_active ? 'Stop WalkGuide' : 'Start WalkGuide'),
                    style: ElevatedButton.styleFrom(
                      backgroundColor: _active ? Colors.red : Colors.blue,
                      foregroundColor: Colors.white,
                    ),
                  ),
                ),

                const SizedBox(height: 8),

                // SOS button
                SizedBox(
                  width: double.infinity,
                  height: 44,
                  child: OutlinedButton.icon(
                    key: const Key('sos_button'),
                    onPressed: () {},
                    icon: const Icon(Icons.sos, color: Colors.red),
                    label: const Text('SOS', style: TextStyle(color: Colors.red)),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _DetectionOverlay extends StatelessWidget {
  final DetectionResult detection;
  const _DetectionOverlay({required this.detection});

  @override
  Widget build(BuildContext context) {
    return Container(
      key: const Key('detection_overlay'),
      margin: const EdgeInsets.symmetric(horizontal: 16),
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: BoxDecoration(
        color: detection.isAlert ? Colors.red.withValues(alpha: 0.85) : Colors.black87,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        '${detection.label} — ${detection.direction} — ${detection.distance}',
        style: const TextStyle(color: Colors.white),
        textAlign: TextAlign.center,
      ),
    );
  }
}

Widget makeTestable(Widget child) => MaterialApp(home: child);

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

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

    group('Rendering awal (inactive)', () {
      testWidgets('menampilkan AppBar dengan judul WalkGuide', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.text('WalkGuide'), findsOneWidget);
      });

      testWidgets('menampilkan status bar dengan status Ready', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.byKey(const Key('status_bar')), findsOneWidget);
        expect(find.text('Ready'), findsOneWidget);
      });

      testWidgets('menampilkan tombol Start WalkGuide', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.byKey(const Key('toggle_button')), findsOneWidget);
        expect(find.text('Start WalkGuide'), findsOneWidget);
      });

      testWidgets('menampilkan tombol SOS', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.byKey(const Key('sos_button')), findsOneWidget);
      });

      testWidgets('menampilkan hint teks saat inactive', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.byKey(const Key('inactive_hint')), findsOneWidget);
      });

      testWidgets('tidak menampilkan detection card saat tidak ada deteksi', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.byKey(const Key('detection_card')), findsNothing);
      });

      testWidgets('menampilkan icon settings di AppBar', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));
        expect(find.byKey(const Key('settings_button')), findsOneWidget);
      });
    });

    // ── Toggle aktif/non-aktif ─────────────────────────────────────────────

    group('Toggle Start/Stop', () {
      testWidgets('tap Start mengubah status menjadi Active', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));

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

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

      testWidgets('tap Start mengubah label tombol menjadi Stop WalkGuide', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));

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

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

      testWidgets('tap Stop mengembalikan status ke Ready', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen(initialActive: true)));

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

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

      testWidgets('tap Stop menghapus detection card', (tester) async {
        const detection = DetectionResult(
          label: 'person',
          confidence: 0.92,
          direction: 'CENTER',
          distance: 'Very Close',
          isAlert: true,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

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

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

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

    // ── Detection overlay ─────────────────────────────────────────────────

    group('Detection display', () {
      testWidgets('menampilkan detection card saat ada deteksi', (tester) async {
        const detection = DetectionResult(
          label: 'car',
          confidence: 0.87,
          direction: 'RIGHT',
          distance: 'Close',
          isAlert: true,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

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

      testWidgets('menampilkan label obstacle yang benar', (tester) async {
        const detection = DetectionResult(
          label: 'motorcycle',
          confidence: 0.75,
          direction: 'LEFT',
          distance: 'Medium',
          isAlert: false,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

        expect(find.byKey(const Key('detection_label')), findsOneWidget);
        expect(find.text('motorcycle'), findsOneWidget);
      });

      testWidgets('menampilkan estimasi jarak obstacle', (tester) async {
        const detection = DetectionResult(
          label: 'person',
          confidence: 0.91,
          direction: 'CENTER',
          distance: 'Very Close',
          isAlert: true,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

        expect(find.text('Very Close'), findsOneWidget);
      });

      testWidgets('menampilkan confidence score dalam persen', (tester) async {
        const detection = DetectionResult(
          label: 'car',
          confidence: 0.87,
          direction: 'CENTER',
          distance: 'Close',
          isAlert: true,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

        expect(find.text('87%'), findsOneWidget);
      });

      testWidgets('menampilkan emoji arah LEFT dengan benar', (tester) async {
        const detection = DetectionResult(
          label: 'person',
          confidence: 0.80,
          direction: 'LEFT',
          distance: 'Close',
          isAlert: false,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

        expect(find.byKey(const Key('direction_emoji')), findsOneWidget);
        expect(find.text('⬅️'), findsOneWidget);
      });

      testWidgets('menampilkan emoji arah RIGHT dengan benar', (tester) async {
        const detection = DetectionResult(
          label: 'car',
          confidence: 0.78,
          direction: 'RIGHT',
          distance: 'Medium',
          isAlert: false,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

        expect(find.text('➡️'), findsOneWidget);
      });

      testWidgets('menampilkan overlay di atas camera preview saat active + ada deteksi',
          (tester) async {
        const detection = DetectionResult(
          label: 'truck',
          confidence: 0.93,
          direction: 'CENTER',
          distance: 'Very Close',
          isAlert: true,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

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

    // ── Error state kamera ────────────────────────────────────────────────

    group('Error state kamera', () {
      testWidgets('menampilkan pesan error kamera saat kamera tidak tersedia', (tester) async {
        await tester.pumpWidget(
          makeTestable(const _StubWalkGuideScreen(cameraError: true)),
        );

        expect(find.byKey(const Key('camera_error_text')), findsOneWidget);
        expect(find.text('Kamera tidak tersedia'), findsOneWidget);
      });

      testWidgets('menampilkan icon error kamera', (tester) async {
        await tester.pumpWidget(
          makeTestable(const _StubWalkGuideScreen(cameraError: true)),
        );

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

      testWidgets('tombol Start di-disable saat kamera error', (tester) async {
        await tester.pumpWidget(
          makeTestable(const _StubWalkGuideScreen(cameraError: true)),
        );

        final btn = tester.widget<ElevatedButton>(find.byKey(const Key('toggle_button')));
        expect(btn.onPressed, isNull);
      });
    });

    // ── Status bar color ──────────────────────────────────────────────────

    group('Status bar warna', () {
      testWidgets('status bar berwarna grey saat inactive', (tester) async {
        await tester.pumpWidget(makeTestable(const _StubWalkGuideScreen()));

        final container = tester.widget<Container>(find.byKey(const Key('status_bar')));
        expect(container.color, Colors.grey);
      });

      testWidgets('status bar berwarna hijau saat active tanpa deteksi', (tester) async {
        await tester.pumpWidget(
          makeTestable(const _StubWalkGuideScreen(initialActive: true)),
        );

        final container = tester.widget<Container>(find.byKey(const Key('status_bar')));
        expect(container.color, Colors.green);
      });

      testWidgets('status bar berwarna merah saat ada obstacle alert', (tester) async {
        const detection = DetectionResult(
          label: 'person',
          confidence: 0.95,
          direction: 'CENTER',
          distance: 'Very Close',
          isAlert: true,
        );
        await tester.pumpWidget(makeTestable(
          const _StubWalkGuideScreen(initialActive: true, initialDetection: detection),
        ));

        final container = tester.widget<Container>(find.byKey(const Key('status_bar')));
        expect(container.color, Colors.red);
      });
    });

    // ── Layout responsif ──────────────────────────────────────────────────

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

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

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

      testWidgets('tidak overflow pada layar 414x896 (iPhone XR)', (tester) async {
        tester.view.physicalSize = const Size(414, 896);
        tester.view.devicePixelRatio = 1.0;
        addTearDown(tester.view.resetPhysicalSize);

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

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