package ru.yandex.webmaster3.internal.user.domain.verification;

import com.datastax.driver.core.utils.UUIDs;
import org.springframework.beans.factory.annotation.Autowired;
import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.data.WebmasterUser;
import ru.yandex.webmaster3.core.events2.HostEventId;
import ru.yandex.webmaster3.core.host.verification.UserHostVerificationInfo;
import ru.yandex.webmaster3.core.host.verification.VerificationCausedBy;
import ru.yandex.webmaster3.core.host.verification.VerificationType;
import ru.yandex.webmaster3.core.host.verification.VerificationTypeScope;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.http.WriteAction;
import ru.yandex.webmaster3.core.http.request.RequestId;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.internal.common.InternalAction;
import ru.yandex.webmaster3.internal.common.security.InternalGrant;
import ru.yandex.webmaster3.internal.user.domain.DomainVerificationState;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.user.service.UserHostsService;
import ru.yandex.webmaster3.storage.verification.HostVerifierService;

/**
 * @author avhaliullin
 */
@Description("Запустить процедуру подтверждения прав на хост")
@WriteAction
public class VerifyDomainAction extends InternalAction<VerifyDomainRequest, VerifyDomainResponse> {
    private final HostVerifierService hostVerifierService;
    private final UserHostsService userHostsService;

    @Autowired
    public VerifyDomainAction(
            HostVerifierService hostVerifierService,
            UserHostsService userHostsService) {
        super(InternalGrant.DOMAIN_VERIFICATION);
        this.hostVerifierService = hostVerifierService;
        this.userHostsService = userHostsService;
    }

    @Override
    public VerifyDomainResponse process(VerifyDomainRequest request) throws WebmasterException {
        long userId = request.getUserId();
        VerificationType verificationType = request.getVerificationType();
        if (!verificationType.visibleIn(VerificationTypeScope.INTERNAL)) {
            return new VerifyDomainResponse.VerificationNotApplicable();
        }

        DomainVerificationState verificationState = request.getDomainVerificationState();
        WebmasterHostId preferredHost = verificationState.getPreferredHost();
        try {
            boolean autoVerified = false;
            UserHostVerificationInfo verificationInfo = verificationState.getVerificationRecords().get(preferredHost);
            if (verificationType == VerificationType.PDD_EMU) {
                // для метода верификации PDD_EMU preferredHost всегда http://domain
                preferredHost = IdUtils.urlToHostId(request.getDomain());
                verificationInfo = verificationState.getVerificationRecords().get(preferredHost);

                // мы сменили preferredHost, возможно он вообще не добавлен в сервис
                if (!verificationState.isAdded(preferredHost)) {
                    HostEventId eventId = HostEventId.createFromUserRequest(
                            new RequestId.FakeRequestId(UUIDs.timeBased()),
                            userId
                    );

                    autoVerified = hostVerifierService.addHostUinInitRecord(new WebmasterUser(userId), preferredHost,
                            verificationInfo, eventId);

                    // при добавление хоста в сервис добавляется новая запись про верификацию
                    verificationInfo = userHostsService.getVerificationInfo(userId, preferredHost);
                }
            }

            if (autoVerified || verificationState.isVerified(preferredHost)) {
                return new VerifyDomainResponse.AlreadyVerifiedError();
            }

            if (!hostVerifierService.isApplicable(preferredHost, userId, verificationType)) {
                return new VerifyDomainResponse.VerificationNotApplicable();
            }

            if (HostVerifierService.isVerificationInProgress(verificationInfo)) {
                return new VerifyDomainResponse.VerificationIsInProgressError();
            }

            boolean launched = hostVerifierService.initiateVerification(
                    verificationInfo,
                    VerificationCausedBy.INTERNAL_API,
                    preferredHost,
                    userId,
                    verificationType
            );

            return launched
                    ? new VerifyDomainResponse.NormalResponse()
                    : new VerifyDomainResponse.VerificationNotApplicable();
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Failed to verify host",
                    new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
        }
    }
}
