import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hub/flutter_flow/random_data_util.dart';
import 'package:hub/main.dart';
import 'package:hub/shared/helpers/base_storage.dart';
import 'package:hub/shared/helpers/storage_helper.dart';
import 'package:integration_test/integration_test.dart';

late WidgetTester widget;

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('Initialization', () {
    group('Navigation', () {
      setUpAll(() async => await initializeApp().then(
          (_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false', Storage.SecureStorage)));
      testWidgets('Test Welcome', (WidgetTester tester) async {
        widget = tester;
        await _testWelcome();
      });
    });

    group('Terms of Use', () {});
  });
  group('Authentication', () {
    group('Sign in', () {
      setUpAll(() async => await initializeApp().then(
          (_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false', Storage.SecureStorage)));
      testWidgets('Test Sign In', (WidgetTester tester) async {
        widget = tester;
        await _testSignIn();
      });
    });
    group('Sign up', () {
      setUpAll(() async => await initializeApp().then(
          (_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false', Storage.SecureStorage)));
      testWidgets('Test Sign Up', (WidgetTester tester) async {
        widget = tester;
        await _testSignUp();
      });
    });
    group('Sign Out', () {
      // Add tests for Sign Out here
    });
    group('Forgot Password', () {
      // setUpAll(() async => await initializeApp().then((_) => StorageUtil().isLogged = false));
      // testWidgets('Test Forgot Password', (WidgetTester tester) async {
      //   widget = tester;
      //   await _testForgotPassword();
      // });
    });
  });
  group('Localization', () {
    // Add tests for Localization here
  });
  group('Networking', () {
    // Add tests for Networking here
  });
  group('Functionality', () {
    // Add tests for Functionality here
  });
  group('Usability', () {
    // Add tests for Usability here
  });
  group('Performance', () {
    // Add tests for Performance here
  });
  group('Security', () {
    // Add tests for Security here
  });
  group('Accessibility', () {
    // Add tests for Accessibility here
  });
  group('Compatibility', () {
    // Add tests for Compatibility here
  });
  group('Internationalization', () {
    // Add tests for Internationalization here
  });
}

Future<void> _testWelcome() async {
  await widget.pumpWidget(const App());
  await widget.pumpAndSettle();
  await _navigateToSignIn();
  await _navigateToSignUp();
  await widget.pumpAndSettle();
  await widget.pumpWidget(const App());
  await widget.pumpAndSettle();
  await _navigateToSignUp();
  await _navigateToSignIn();
  await widget.pumpAndSettle();
}

Future<void> _testSignIn() async {
  await widget.pumpWidget(const App());
  await _navigateToSignIn();
  await _auth({'emailTextFormField': 'erro@exemplo.com', 'passwordTextFormField': '12345678'});
  await _auth({'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'});
}

Future<void> _testSignUp() async {
  await widget.pumpWidget(const App());
  await _navigateToSignUp();

  var credentials = {
    'nameTextFormField': 'app',
    'emailTextFormField': 'email_app@exemplo.com',
    'passwordTextFormField': '12345678'
  };
  await _auth(credentials);

  var name = randomString(7, 7, true, true, true);
  var email = '$name@example.com';
  var password = '12345678';
  credentials = {'nameTextFormField': name, 'emailTextFormField': email, 'passwordTextFormField': password};
  await _navigateToSignUp();
  await _auth(credentials);
  credentials = {'emailTextFormField': email, 'passwordTextFormField': password};
  await _auth(credentials);
}

Future<void> _testForgotPassword() async {
  await widget.pumpWidget(const App());
  await _navigateToSignIn();
  await _recoveryPassword();

  var addr = randomString(5, 5, true, true, true);
  var credentials = {'recoveryTextFormField': '$addr@exemple.com'};
  await _send(credentials);

  await Future.delayed(const Duration(seconds: 2));

  await _recoveryPassword();
  credentials = {'recoveryTextFormField': 'email_app@exemple.com'};
  await _send(credentials);
}

Future<void> _recoveryPassword() async {
  await widget.pumpAndSettle();
  final Finder forgotPassword = find.byKey(const ValueKey<String>('ForgotPassword'));
  if (forgotPassword.evaluate().isNotEmpty) await widget.tap(forgotPassword);
  await widget.ensureVisible(forgotPassword);
  await widget.pumpAndSettle();
}

Future<void> _navigateBackUsingSystemGesture() async =>
    IntegrationTestWidgetsFlutterBinding.instance.keyboard.isLogicalKeyPressed(LogicalKeyboardKey.escape);
Future<void> _navigateToSignUp() async {
  await widget.pumpAndSettle();
  final Finder navToSignUp = find.byKey(const ValueKey<String>('toggleSignUpPage'));
  if (navToSignUp.evaluate().isNotEmpty) {
    await widget.tap(navToSignUp);
    await widget.pumpAndSettle();
  }
}

Future<void> _navigateToSignIn() async {
  await widget.pumpAndSettle();
  final Finder navToSignIn = find.byKey(const ValueKey<String>('toggleSignInPage'));
  expect(navToSignIn, findsOneWidget);
  if (navToSignIn.evaluate().isNotEmpty) {
    await widget.tap(navToSignIn);
    await widget.pumpAndSettle();
  }
}

Future<void> _auth(Map<String, dynamic> credentials) async {
  await _enterCredentials(credentials);
  await _submit('SubmitButtonWidget');
}

Future<void> _send(Map<String, dynamic> credentials) async {
  await _enterCredentials(credentials);
  await _submit('SendButtonWidget');
}

Future<void> _enterCredentials(Map<String, dynamic> credentials) async {
  await widget.pumpAndSettle();
  for (var entry in credentials.entries) {
    final Finder field = find.byKey(ValueKey<String>(entry.key));
    await widget.pumpAndSettle();
    expect(field, findsOneWidget);
    await widget.enterText(field, entry.value);
    await widget.pumpAndSettle();
  }
  await widget.pumpAndSettle();
}

Future<void> _submit(String key) async {
  await widget.pumpAndSettle();
  final Finder submitButton = find.byKey(ValueKey<String>(key));
  await widget.pumpAndSettle();
  if (submitButton.evaluate().isNotEmpty) {
    await widget.tap(submitButton);
    await widget.pumpAndSettle();
  }

  final Finder throwExceptionWidget = find.byKey(const ValueKey<String>('ThrowExceptionWidget'));
  await widget.pumpAndSettle();
  if (throwExceptionWidget.evaluate().isNotEmpty) {
    await widget.ensureVisible(throwExceptionWidget);
    await widget.tap(throwExceptionWidget);
    await widget.pumpAndSettle();
  } else {
    await _navigateBackUsingSystemGesture();
  }
}
