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

import java.util.List;
import java.util.stream.Collectors;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Value;
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.ReadAction;
import ru.yandex.webmaster3.core.http.RequestQueryProperty;
import ru.yandex.webmaster3.storage.abt.dao.AbtExperimentYDao;
import ru.yandex.webmaster3.storage.abt.dao.AbtExperimentsHistoryYDao;
import ru.yandex.webmaster3.storage.abt.hash.AbtHashExperimentYDao;
import ru.yandex.webmaster3.storage.abt.hash.HashExperimentRecord;
import ru.yandex.webmaster3.storage.abt.hash.HashField;
import ru.yandex.webmaster3.storage.abt.hash.HashFunction;
import ru.yandex.webmaster3.storage.abt.model.Experiment;
import ru.yandex.webmaster3.storage.abt.model.ExperimentHistory;
import ru.yandex.webmaster3.storage.abt.model.IExperiment;
import ru.yandex.webmaster3.storage.abt.model.SimpleExperiment;

@ReadAction
@Component("/experiment/details")
@AllArgsConstructor(onConstructor_ = @Autowired)
public class GetExperimentDetailInfoAction extends Action<GetExperimentDetailInfoAction.Req, ActionResponse> {
    private final AbtExperimentYDao abtExperimentYDao;
    private final AbtExperimentsHistoryYDao abtExperimentsHistoryYDao;
    private final AbtHashExperimentYDao abtHashExperimentYDao;

    @Override
    public ActionResponse process(GetExperimentDetailInfoAction.Req request) throws WebmasterException {
        IExperiment experiment = abtExperimentYDao.select(request.getExperiment());
        if (experiment == null) {
            experiment = Experiment.valueOf(request.getExperiment());
        }

        List<HashExperimentRecord> hashExperimentRecord = abtHashExperimentYDao.getRecords(experiment.getName());
        List<ExperimentHistory> experimentStatistics = abtExperimentsHistoryYDao.getRecords(experiment.getName());

        return new Res(
                new SimpleExperiment(experiment.getName(), experiment.getDescription(), experiment.getScope(), experiment.isActive()),
                hashExperimentRecord.stream().map(HashRecord::convert).collect(Collectors.toList()),
                experimentStatistics
        );
    }

    @Getter
    public static class Req implements ActionRequest {
        private String experiment;

        @RequestQueryProperty(required = true)
        public void setExperiment(String experiment) {
            this.experiment = experiment;
        }
    }

    @Getter
    @AllArgsConstructor
    public static class Res implements ActionResponse.NormalResponse {
        private SimpleExperiment experiment;
        private List<HashRecord> hashExperiment;
        private List<ExperimentHistory> experimentStatistics;
    }

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

    @Value
    public static class HashRecord {
        String experiment;
        String group;
        HashField hashField;
        HashFunction hashFunction;
        int minValue;
        int maxValue;

        public static HashRecord convert(HashExperimentRecord item) {
            return new HashRecord(item.getExperiment(),
                    item.getGroup(),
                    item.getHashField(),
                    item.getHashFunction(),
                    (int) (item.getMinValue() * 100),
                    (int) (item.getMaxValue() * 100));
        }
    }

    enum ErrorResponseCode {
        BAD_EXPERIMENT
    }
}
