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

import java.util.Collection;
import java.util.List;
import java.util.UUID;

import com.datastax.driver.core.utils.UUIDs;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.data.WebmasterUser;
import ru.yandex.webmaster3.core.host.verification.UserHostVerificationInfo;
import ru.yandex.webmaster3.core.host.verification.VerificationCausedBy;
import ru.yandex.webmaster3.core.http.WriteAction;
import ru.yandex.webmaster3.core.user.UserVerifiedHost;
import ru.yandex.webmaster3.core.worker.client.WorkerClient;
import ru.yandex.webmaster3.core.worker.task.VerifyHostTaskData;
import ru.yandex.webmaster3.core.worker.task.WorkerTaskPriority;
import ru.yandex.webmaster3.internal.common.InternalAction;
import ru.yandex.webmaster3.internal.common.security.ActionInternalGrant;
import ru.yandex.webmaster3.internal.common.security.InternalGrant;
import ru.yandex.webmaster3.storage.delegation.HostDelegationRecord;
import ru.yandex.webmaster3.storage.delegation.UserHostDelegationsYDao;
import ru.yandex.webmaster3.storage.user.dao.UserHostVerificationYDao;
import ru.yandex.webmaster3.storage.user.service.UserHostsService;

/**
 * @author avhaliullin
 */
@WriteAction
@Description("Запросить перепроверку на домен для указанного пользователя. В случае, если права были делегированы другим пользователем - отменить делегирование")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@ActionInternalGrant(InternalGrant.DOMAIN_VERIFICATION)
public class ResetDomainVerificationAction extends InternalAction<ResetDomainVerificationRequest, ResetDomainVerificationResponse> {

    private final UserHostsService userHostsService;
    private final UserHostVerificationYDao userHostVerificationYDao;
    private final WorkerClient workerClient;
    private final UserHostDelegationsYDao userHostDelegationsYDao;

    @Override
    public ResetDomainVerificationResponse process(ResetDomainVerificationRequest request) {
        boolean hasInheritedVerification = request.getDomainVerificationState().getVerifiedHosts().values()
                .stream().anyMatch(uvh -> uvh.getVerificationType().isCanBeDelegated());
        long forUserId = request.getForUserId();
        long requestedByUserId = request.getUserId();
        List<UserVerifiedHost> verifiedHosts = userHostsService.getVerifiedHosts(
                new WebmasterUser(forUserId),
                request.getDomainVerificationState().getAllPossibleDomainHosts()
        );

        if (hasInheritedVerification) {
            cancelDelegations(
                    forUserId,
                    request.getDomainVerificationState().getAllPossibleDomainHosts(),
                    requestedByUserId
            );
        }
        for (UserVerifiedHost verifiedHost : verifiedHosts) {
            launchRecheck(forUserId, verifiedHost, requestedByUserId);
        }
        return new ResetDomainVerificationResponse.NormalResponse();
    }

    private void launchRecheck(long forUserId, UserVerifiedHost verifiedHost, long requestedByUserId)  {
        UUID recordId = UUIDs.timeBased();
        userHostVerificationYDao.addVerificationRecord(UserHostVerificationInfo.createVerificationStartRecord(
                recordId, forUserId, verifiedHost.getWebmasterHostId(), verifiedHost.getVerificationType(),
                verifiedHost.getVerificationUin(), VerificationCausedBy.RESET_REQUESTED, requestedByUserId
        ));
        workerClient.enqueueTask(
                VerifyHostTaskData.createTaskData(
                        verifiedHost.getWebmasterHostId(),
                        forUserId,
                        recordId,
                        verifiedHost.getVerificationType(),
                        WorkerTaskPriority.HIGH
                )
        );
    }

    private void cancelDelegations(long forUserId, Collection<WebmasterHostId> hostIds, long requestedByUserId)  {
        for (WebmasterHostId hostId : hostIds) {
            HostDelegationRecord delegationRecord =
                    userHostDelegationsYDao.getDelegationForHostToUser(hostId, forUserId);
            if (delegationRecord != null && !delegationRecord.isCancelled()) {
                userHostDelegationsYDao.addDelegationRecord(delegationRecord.copyCancelled(requestedByUserId));
            }
        }
    }
}
