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


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.WebmasterException;
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.model.ExperimentScope;
import ru.yandex.webmaster3.storage.abt.model.IExperiment;
import ru.yandex.webmaster3.storage.abt.model.SimpleExperiment;


@WriteAction
@Component("/experiment/action")
@AllArgsConstructor(onConstructor_ = @Autowired)
public class UpdateExperimentAction extends Action<UpdateExperimentAction.Req, ActionResponse> {
    private final AbtExperimentYDao abtExperimentYDao;

    @Override
    public ActionResponse process(Req request) throws WebmasterException {
        if (!ObjectUtils.anyNotNull(request.getDescription(), request.getScope(), request.getTaskType())) {
            return new Response();
        }

        final IExperiment oldExperiment = abtExperimentYDao.select(request.getExperiment());

        if (oldExperiment != null) {
            final SimpleExperiment newExperimentInfo = new SimpleExperiment(request.getExperiment(), request.getDescription(), request.getScope(), request.getTaskType() == TaskType.ENABLE);
            final SimpleExperiment experiment = mergeExperimentsInfo(oldExperiment, newExperimentInfo);

            // если эксперимент лежит в кассандре, то просто обновляем, если это внутринний эксп из класса  Experiment то
            // кладем в кассандру эксп. Он будет являться доминирующим
            abtExperimentYDao.update(experiment);

            return new Response();
        }

        return new ErrorResponse();
    }

    SimpleExperiment mergeExperimentsInfo(IExperiment oldExperimentInfo, IExperiment newExperimentInfo) {
        final String description = newExperimentInfo.getDescription() == null ? oldExperimentInfo.getDescription() : newExperimentInfo.getDescription();
        final ExperimentScope scope = newExperimentInfo.getScope() == null ? oldExperimentInfo.getScope() : newExperimentInfo.getScope();
        final boolean active = newExperimentInfo.isActive();

        return new SimpleExperiment(oldExperimentInfo.getName(), description, scope, active);
    }


    @Getter
    @Setter(onMethod_ = @RequestQueryProperty())
    public static class Req implements ActionRequest {
        @Setter(onMethod_ = @RequestQueryProperty(required = true))
        private String experiment;
        private String description;
        private ExperimentScope scope;
        @Setter(onMethod_ = @RequestQueryProperty(required = true))
        private TaskType taskType;
    }

    public static class Response implements ActionResponse.NormalResponse {
    }

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

    enum TaskType {
        ENABLE, DISABLE
    }

    enum ErrorResponseCode {
        BAD_EXPERIMENT
    }
}
