package ru.yandex.webmaster3.storage.verification;

import java.util.Optional;
import java.util.UUID;

import lombok.Setter;
import org.joda.time.DateTime;

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.host.verification.IUserHostVerifier;
import ru.yandex.webmaster3.core.host.verification.VerificationCausedBy;
import ru.yandex.webmaster3.core.host.verification.VerificationFailInfo;
import ru.yandex.webmaster3.core.host.verification.fail.DelegationCancelledFailInfo;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.user.UserVerifiedHost;
import ru.yandex.webmaster3.storage.delegation.HostDelegationRecord;
import ru.yandex.webmaster3.storage.delegation.UserHostDelegationsYDao;
import ru.yandex.webmaster3.storage.user.service.UserHostsService;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;

/**
 * @author avhaliullin
 */
public class DelegationVerifier implements IUserHostVerifier {
    @Setter
    private UserHostDelegationsYDao userHostDelegationsYDao;
    @Setter
    private UserHostsService userHostsService;

    @Override
    public Optional<VerificationFailInfo> verify(long userId, WebmasterHostId hostId, UUID recordId, long verificationUin, VerificationCausedBy verificationCausedBy) {
        try {
            HostDelegationRecord delegationRecord = userHostDelegationsYDao.getDelegationForHostToUser(hostId, userId);
            if (delegationRecord == null) {
                return Optional.of(new DelegationCancelledFailInfo(null, null));
            }
            UserVerifiedHost verifiedHost =
                    userHostsService.getVerifiedHost(new WebmasterUser(delegationRecord.getFromUser()), hostId);
            if (verifiedHost == null || !verifiedHost.getVerificationType().isCanBeDelegated()) {
                userHostDelegationsYDao.addDelegationRecord(delegationRecord.copyCancelled(delegationRecord.getFromUser()));
                return Optional.of(new DelegationCancelledFailInfo(delegationRecord.getFromUser(), DateTime.now()));
            }
            if (delegationRecord.isCancelled()) {
                return Optional.of(new DelegationCancelledFailInfo(delegationRecord.getCancelledByUser(), delegationRecord.getCancelledDate()));
            }
            return Optional.empty();
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Failed to verify delegation",
                    new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
        }
    }

    @Override
    public boolean isApplicable(WebmasterHostId hostId, long userId) {
        return true;
    }
}
