import 'package:demo/app_error.dart';
import 'package:demo/demo.dart';
import 'package:fpdart/fpdart.dart';
import 'package:test/test.dart';

void main() {
  group("User Registration Tests", () {
    test("Valid name and email results in successful registration", () async {
      final name = "John Doe";
      final email = "newuser@example.com";

      final result =
          await Either<AppError, (String, String)>.right((name, email))
              .flatMap((userData) => validateName(userData.$1).flatMap(
                  (validName) => validateEmail(userData.$2)
                      .map((validEmail) => (validName, validEmail))))
              .toTaskEither()
              .flatMap((validUser) => checkEmailExists(validUser.$2).flatMap(
                  (exists) => exists
                      ? AppError.left("Email already exists",
                              type: AppErrorType.ValidationError)
                          .toTaskEither()
                      : saveUser(validUser.$1, validUser.$2)))
              .flatMap((_) => sendWelcomeEmail(email))
              .run();

      result.match(
        (error) => fail("Test failed with error: ${error.message}"),
        (success) => expect(success, equals(true)),
      );
    });

    test("Invalid email format returns validation error", () async {
      final name = "John Doe";
      final email = "invalid-email";

      final result =
          await Either<AppError, (String, String)>.right((name, email))
              .flatMap((userData) => validateName(userData.$1).flatMap(
                  (validName) => validateEmail(userData.$2)
                      .map((validEmail) => (validName, validEmail))))
              .toTaskEither()
              .run();

      result.match(
        (error) {
          expect(error.message, equals("Invalid email format"));
          expect(error.type, equals(AppErrorType.ValidationError));
        },
        (success) => fail("Test succeeded unexpectedly"),
      );
    });

    test("Existing email results in error", () async {
      final name = "John Doe";
      final email = "existing@example.com";

      final result =
          await Either<AppError, (String, String)>.right((name, email))
              .flatMap((userData) => validateName(userData.$1).flatMap(
                  (validName) => validateEmail(userData.$2)
                      .map((validEmail) => (validName, validEmail))))
              .toTaskEither()
              .flatMap((validUser) => checkEmailExists(validUser.$2).flatMap(
                  (exists) => exists
                      ? AppError.left("Email already exists",
                              type: AppErrorType.ValidationError)
                          .toTaskEither()
                      : saveUser(validUser.$1, validUser.$2)))
              .run();

      result.match(
        (error) => expect(error.message, equals("Email already exists")),
        (success) => fail("Test succeeded unexpectedly"),
      );
    });

    test("Empty name returns validation error", () async {
      final name = "";
      final email = "newuser@example.com";

      final result =
          await Either<AppError, (String, String)>.right((name, email))
              .flatMap((userData) => validateName(userData.$1).flatMap(
                  (validName) => validateEmail(userData.$2)
                      .map((validEmail) => (validName, validEmail))))
              .toTaskEither()
              .run();

      result.match(
        (error) => expect(
            error,
            equals(AppError(
                message: "Name cannot be empty",
                type: AppErrorType.ValidationError))),
        (success) => fail("Test succeeded unexpectedly"),
      );
    });

    test("Error while sending welcome email is handled gracefully", () async {
      final name = "John Doe";
      final email = "newuser@example.com";

      // Simuliere einen Fehler beim Senden der Begrüßungs-E-Mail
      TaskEither<AppError, bool> sendWelcomeEmail(String email) {
        return TaskEither.left(AppError(
          message: "Error sending welcome email",
          type: AppErrorType.NetworkError,
        ));
      }

      final result =
          await Either<AppError, (String, String)>.right((name, email))
              .flatMap((userData) => validateName(userData.$1).flatMap(
                  (validName) => validateEmail(userData.$2)
                      .map((validEmail) => (validName, validEmail))))
              .toTaskEither()
              .flatMap((validUser) =>
                  checkEmailExists(validUser.$2).flatMap((exists) => exists
                      ? AppError.left(
                          "Email already exists",
                          type: AppErrorType.ValidationError,
                        ).toTaskEither()
                      : saveUser(validUser.$1, validUser.$2)))
              .flatMap((_) => sendWelcomeEmail(email))
              .run();

      result.match(
        (error) {
          expect(error.message, equals("Error sending welcome email"));
          expect(error.type, equals(AppErrorType.NetworkError));
        },
        (success) => fail("Test succeeded unexpectedly"),
      );
    });
  });
}
