import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fotodocumentation/controller/customer_controller.dart';
import 'package:fotodocumentation/dto/customer_dto.dart' show CustomerDto, CustomerListDto;
import 'package:fotodocumentation/dto/picture_dto.dart';
import 'package:fotodocumentation/pages/customer/picture_fullscreen_dialog.dart';
import 'package:fotodocumentation/utils/di_container.dart';
import 'package:fotodocumentation/utils/global_router.dart';
import 'package:fotodocumentation/utils/login_credentials.dart';
import 'package:mockito/mockito.dart';

import '../testing/test_utils.dart';
import '../testing/test_utils.mocks.dart';

// Minimal valid base64 encoded 1x1 pixel PNG image
const String _testImage = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  DiContainer.instance.initState();
  DiContainer.instance.put(LoginCredentials, getDefaultLoginCredentials());

  late CustomerDto customerDto;
  late PictureDto pictureDto1;
  late PictureDto pictureDto2;
  late PictureDto pictureDto3;
  late MockCustomerController mockCustomerController;

  setUp(() {
    pictureDto1 = PictureDto(
      id: 1,
      comment: 'First picture comment',
      category: 'category1',
      image: _testImage,
      pictureDate: DateTime(2024, 1, 15),
      username: 'user1',
      evaluation: 1,
    );

    pictureDto2 = PictureDto(
      id: 2,
      comment: 'Second picture comment',
      category: 'category2',
      image: _testImage,
      pictureDate: DateTime(2024, 2, 20),
      username: 'user2',
      evaluation: 1,
    );

    pictureDto3 = PictureDto(
      id: 3,
      comment: null,
      category: 'category3',
      image: _testImage,
      pictureDate: DateTime(2024, 3, 25),
      username: 'user3',
      evaluation: 1,
    );

    customerDto = CustomerDto(
      id: 1,
      name: 'Test Apotheke',
      customerNumber: 'CUST001',
      pictures: [pictureDto1, pictureDto2, pictureDto3],
    );

    mockCustomerController = MockCustomerController();
    DiContainer.instance.put(CustomerController, mockCustomerController);
  });

  group('PictureWidget', () {
    testWidgets('displays customer information correctly', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Verify customer name is displayed
      expect(find.text('Test Apotheke'), findsOneWidget);

      // Verify customer number is displayed
      expect(find.text('CUST001'), findsOneWidget);

      // Verify labels are displayed
      expect(find.text('KUNDENNUMMER'), findsOneWidget);
      expect(find.text('KOMMENTAR'), findsOneWidget);
    });

    testWidgets('displays picture comment', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Verify the comment is displayed
      expect(find.text('First picture comment'), findsOneWidget);
    });

    testWidgets('displays empty string when comment is null', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // The comment field should be empty but the label should exist
      expect(find.text('KOMMENTAR'), findsOneWidget);
    });

    testWidgets('shows both navigation buttons at bottom', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Both navigation buttons should always be visible at the bottom
      expect(find.byKey(Key("navigate_left")), findsOneWidget);
      expect(find.byKey(Key("navigate_right")), findsOneWidget);
    });

    testWidgets('shows both navigation buttons when on middle picture', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Both navigation buttons should be visible
      expect(find.byKey(Key("navigate_left")), findsOneWidget);
      expect(find.byKey(Key("navigate_right")), findsOneWidget);
    });

    testWidgets('shows both navigation buttons on last picture', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Both navigation buttons should be visible (right one is disabled)
      expect(find.byKey(Key("navigate_left")), findsOneWidget);
      expect(find.byKey(Key("navigate_right")), findsOneWidget);
    });

    testWidgets('navigates to next picture when right button is tapped', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Verify first picture comment is shown
      expect(find.text('First picture comment'), findsOneWidget);

      // Tap right navigation button
      await tester.tap(find.byIcon(Icons.chevron_right));
      await tester.pumpAndSettle();

      // Verify second picture comment is now shown
      expect(find.text('Second picture comment'), findsOneWidget);
      expect(find.text('First picture comment'), findsNothing);
    });

    testWidgets('navigates to previous picture when left button is tapped', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/2");
      await tester.pumpAndSettle();

      // Verify second picture comment is shown
      expect(find.text('Second picture comment'), findsOneWidget);

      // Tap left navigation button
      await tester.tap(find.byKey(Key("navigate_left")));
      await tester.pumpAndSettle();

      // Verify first picture comment is now shown
      expect(find.text('First picture comment'), findsOneWidget);
      expect(find.text('Second picture comment'), findsNothing);
    });

    testWidgets('shows disabled navigation buttons when only one picture', (WidgetTester tester) async {
      setScreenSize(tester, 1024, 1024);

      final singlePictureCustomer = CustomerDto(
        id: 1,
        name: 'Test Apotheke',
        customerNumber: 'CUST001',
        pictures: [pictureDto1],
      );

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => singlePictureCustomer);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Both navigation buttons should be shown but disabled
      expect(find.byKey(Key("navigate_left")), findsOneWidget);
      expect(find.byKey(Key("navigate_right")), findsOneWidget);
    });

    testWidgets('opens fullscreen dialog when image is tapped', (WidgetTester tester) async {
      setScreenSize(tester, 2048, 2048);

      when(mockCustomerController.get(id: 1)).thenAnswer((_) async => customerDto);
      when(mockCustomerController.getAll("", "")).thenAnswer((_) async => _list);

      await pumpAppConfig(tester, "${GlobalRouter.pathHome}${GlobalRouter.pathPicture}/1/1");
      await tester.pumpAndSettle();

      // Find the GestureDetector with the image key
      final imageFinder = find.byKey(const Key("image"));
      expect(imageFinder, findsOneWidget);

      // Ensure the widget is visible first
      await tester.ensureVisible(imageFinder);
      await tester.pumpAndSettle();

      // Tap the image - use warnIfMissed: false since the Image.memory may have
      // rendering issues in test environment but the GestureDetector should still work
      await tester.tap(imageFinder, warnIfMissed: false);
      await tester.pumpAndSettle();

      // Verify fullscreen dialog is shown
      expect(find.byType(PictureFullscreenDialog), findsOneWidget);
    });
  });
}

List<CustomerListDto> _list = [CustomerListDto(id: 1, customerNumber: "CODE1", name: "Customer 1"), CustomerListDto(id: 2, customerNumber: "CODE2", name: "Customer 2")];
