package ru.yandex.webmaster3.worker.http.abt;


import com.google.common.base.Strings;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.joda.time.Instant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.blackbox.service.BlackboxUsersService;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.http.Action;
import ru.yandex.webmaster3.core.http.ActionRequest;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.http.RequestQueryProperty;
import ru.yandex.webmaster3.core.http.WriteAction;
import ru.yandex.webmaster3.storage.abt.dao.AbtExperimentYDao;
import ru.yandex.webmaster3.storage.abt.dao.AbtExperimentsHistoryYDao;
import ru.yandex.webmaster3.storage.abt.dao.AbtHostExperimentYDao;
import ru.yandex.webmaster3.storage.abt.dao.AbtUserExperimentYDao;
import ru.yandex.webmaster3.storage.abt.model.ExperimentInfo;
import ru.yandex.webmaster3.storage.abt.model.ExperimentScope;
import ru.yandex.webmaster3.storage.abt.model.IExperiment;
import ru.yandex.webmaster3.storage.download.DownloadStatus;


@WriteAction
@Component("/experiment/add")
@AllArgsConstructor(onConstructor_ = @Autowired)
public class AddExperimentAction extends Action<AddExperimentAction.Req, ActionResponse> {
    private final AbtExperimentYDao abtExperimentYDao;
    private final AbtExperimentsHistoryYDao abtExperimentsHistoryYDao;
    private final AbtHostExperimentYDao abtHostExperimentYDao;
    private final AbtUserExperimentYDao abtUserExperimentYDao;
    private final BlackboxUsersService blackboxExternalYandexUsersService;

    @Override
    public ActionResponse process(Req request) throws WebmasterException {
        IExperiment experiment = abtExperimentYDao.select(request.getExperiment());

        if (experiment != null) {
            ExperimentInfo experimentInfo = new ExperimentInfo(request.getExperiment(), request.getGroup());

            if (request.getHostId() != null) {
                long delta;
                if (request.getTaskType() == TaskType.ADD) {
                    abtHostExperimentYDao.insert(request.getHostId(), experimentInfo);
                    delta = 1L;
                } else {
                    abtHostExperimentYDao.delete(request.getHostId(), experimentInfo);
                    delta = -1L;
                }

                abtExperimentsHistoryYDao.insert(
                        request.getExperiment(),
                        request.getGroup(),
                        ExperimentScope.HOST.name(),
                        Instant.now(),
                        delta,
                        request.getTaskType() + " experiment: " + request.getExperiment() + " group: " +
                                request.getGroup() + " host_id: " + request.getHostId(),
                        DownloadStatus.DONE
                );
            }

            if (!Strings.isNullOrEmpty(request.getLogin())) {
                var userLogin = blackboxExternalYandexUsersService.getUserByLogin(request.getLogin());
                if (userLogin != null) {
                    request.setUserId(userLogin.getUserId());
                }
            }

            if (request.getUserId() != null) {
                long delta;

                if (request.getTaskType() == TaskType.ADD) {
                    abtUserExperimentYDao.insert(request.getUserId(), experimentInfo);
                    delta = 1L;
                } else {
                    abtUserExperimentYDao.delete(request.getUserId(), experimentInfo);
                    delta = -1L;
                }

                abtExperimentsHistoryYDao.insert(
                        request.getExperiment(),
                        request.getGroup(),
                        ExperimentScope.USER.name(),
                        Instant.now(),
                        delta,
                        request.getTaskType() + " experiment: " + request.getExperiment() +
                                " group: " + request.getGroup() + " user: " + request.getUserId(),
                        DownloadStatus.DONE
                );
            }

            return new Response();
        }

        return new ErrorResponse();
    }


    @Getter
    @Setter(onMethod_ = @RequestQueryProperty(required = true))
    public static class Req implements ActionRequest {
        private String experiment;
        private String group;
        @Setter(onMethod_ = @RequestQueryProperty)
        private WebmasterHostId hostId;
        @Setter(onMethod_ = @RequestQueryProperty)
        private Long userId;
        @Setter(onMethod_ = @RequestQueryProperty)
        private String login;
        private TaskType taskType;
    }

    public static class Response implements ActionResponse.NormalResponse {
    }

    @Getter
    @AllArgsConstructor
    public static class ErrorResponse implements ActionResponse.ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return GetExperimentDetailInfoAction.ErrorResponseCode.BAD_EXPERIMENT;
        }
    }

    enum TaskType {
        ADD, REMOVE
    }

    enum ErrorResponseCode {
        BAD_EXPERIMENT
    }
}
