package ru.otus.mobile.extensions;

import com.google.inject.Guice;
import com.google.inject.Injector;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import ru.otus.mobile.annotations.MobileUser;
import ru.otus.mobile.config.TestAccount;
import ru.otus.mobile.db.DbClient;
import ru.otus.mobile.driver.MobileSession;
import ru.otus.mobile.driver.MobileSessionFactory;
import ru.otus.mobile.guice.CoreModule;
import ru.otus.mobile.page.LoginPage;

public final class MobileExtension implements
        BeforeEachCallback,
        AfterEachCallback {
    private static final ExtensionContext.Namespace NAMESPACE =
            ExtensionContext.Namespace.create(MobileExtension.class);
    private static final String SESSION_KEY = "mobile.session";

    @Override
    public void beforeEach(ExtensionContext context) {
        Injector injector = rootInjector(context);
        TestAccount account = resolveAccount(context);
        injector.getInstance(DbClient.class).resetData(account);

        MobileSessionFactory sessionFactory = injector.getInstance(MobileSessionFactory.class);
        MobileSession session = sessionFactory.create(account, context.getDisplayName());
        session.activate();
        session.injectMembers(context.getRequiredTestInstance());
        context.getStore(NAMESPACE).put(SESSION_KEY, session);
        injector.getInstance(LoginPage.class).login(account);
    }

    @Override
    public void afterEach(ExtensionContext context) {
        MobileSession session = context.getStore(NAMESPACE).remove(SESSION_KEY, MobileSession.class);
        if (session != null) {
            session.close();
        }
    }

    private Injector rootInjector(ExtensionContext context) {
        return context.getRoot()
                .getStore(NAMESPACE)
                .getOrComputeIfAbsent("root.injector", key -> Guice.createInjector(new CoreModule()), Injector.class);
    }

    private TestAccount resolveAccount(ExtensionContext context) {
        MobileUser annotation = context.getRequiredTestClass().getAnnotation(MobileUser.class);
        if (annotation == null) {
            throw new IllegalStateException("Test class must be annotated with @MobileUser.");
        }
        return annotation.value();
    }
}
