import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:userfront/features/profile/data/models/user_profile_model.dart';
import 'package:userfront/features/profile/domain/notifiers/profile_notifier.dart';
import 'package:userfront/features/profile/presentation/pages/profile_page.dart';

// Mocking the profile notifier
class MockProfileNotifier extends ProfileNotifier {
  UserProfile? _profile;
  bool updateCalled = false;
  String? updatedName;

  @override
  Future<UserProfile?> build() async {
    _profile = UserProfile(
      id: 'test-id',
      email: 'test@example.com',
      name: 'Original Name',
      phone: '01012345678',
      department: 'Dev',
      affiliationType: 'employee',
      companyCode: 'C100',
    );
    return _profile;
  }

  @override
  Future<UserProfile?> loadProfile() async {
    state = const AsyncValue.loading();
    state = AsyncValue.data(_profile);
    return _profile;
  }

  @override
  Future<void> updateProfile({
    String? name,
    String? phone,
    String? department,
  }) async {
    updateCalled = true;
    updatedName = name;
    _profile = _profile!.copyWith(
      name: name ?? _profile!.name,
      phone: phone ?? _profile!.phone,
      department: department ?? _profile!.department,
    );
    state = AsyncValue.data(_profile);
  }
}

void main() {
  testWidgets(
    'ProfilePage explicit save button UX flow (Edit -> Cancel -> Edit -> Save)',
    (tester) async {
      final recordedErrors = <FlutterErrorDetails>[];
      final previousOnError = FlutterError.onError;
      FlutterError.onError = (details) {
        final text = details.exceptionAsString();
        if (text.contains('A RenderFlex overflowed')) {
          return;
        }
        recordedErrors.add(details);
      };
      addTearDown(() {
        FlutterError.onError = previousOnError;
      });

      tester.view.physicalSize = const Size(1920, 1080);
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.resetPhysicalSize);
      addTearDown(tester.view.resetDevicePixelRatio);

      final mockNotifier = MockProfileNotifier();

      await tester.pumpWidget(
        ProviderScope(
          overrides: [profileProvider.overrideWith(() => mockNotifier)],
          child: const MaterialApp(home: Scaffold(body: ProfilePage())),
        ),
      );

      await tester.pumpAndSettle();

      // 1. Entering edit mode
      final editButton = find.byKey(const Key('profile-name-edit-button'));
      expect(editButton, findsOneWidget);
      await tester.tap(editButton);
      await tester.pumpAndSettle();

      final inputField = find.byKey(const Key('profile-name-input'));
      expect(inputField, findsOneWidget);

      // 2. Testing cancel flow
      await tester.enterText(inputField, 'Changed Name');
      await tester.pumpAndSettle();

      final cancelButton = find.byKey(const Key('profile-name-cancel-button'));
      await tester.tap(cancelButton);
      await tester.pumpAndSettle();

      // After cancellation, the field should be read-only again.
      expect(find.byKey(const Key('profile-name-input')), findsNothing);
      // Find text could be part of ListTile
      expect(find.text('Original Name'), findsWidgets);

      // 3. Re-enter edit mode and explicitly save
      await tester.tap(find.byKey(const Key('profile-name-edit-button')));
      await tester.pumpAndSettle();

      await tester.enterText(
        find.byKey(const Key('profile-name-input')),
        'Saved Name',
      );
      await tester.pumpAndSettle();

      final saveButton = find.byKey(const Key('profile-name-save-button'));
      await tester.tap(saveButton);
      await tester.pumpAndSettle();
      await tester.pump(const Duration(seconds: 4));
      await tester.pumpAndSettle();

      FlutterError.onError = previousOnError;

      // Verify the mock received the update
      expect(mockNotifier.updateCalled, isTrue);
      expect(mockNotifier.updatedName, 'Saved Name');
      expect(recordedErrors, isEmpty);
    },
  );
}
