package ru.yandex.qe.dispenser.domain.dao.quota.request.collector;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

import javax.annotation.Nonnull;

import org.jetbrains.annotations.NotNull;
import org.postgresql.util.PGobject;

import ru.yandex.qe.dispenser.domain.QuotaChangeRequest;
import ru.yandex.qe.dispenser.domain.dao.SqlDaoBase;
import ru.yandex.qe.dispenser.domain.dao.SqlUtils;
import ru.yandex.qe.dispenser.domain.dao.goal.OkrAncestors;
import ru.yandex.qe.dispenser.domain.dao.quota.request.ReportQuotaChangeRequest;

public class ReportRequestCollector extends BaseRequestCollector<Stream<ReportQuotaChangeRequest>> {

    private final Map<Long, Map<Long, String>> requestGoalAnswersByRequestId = new HashMap<>();
    private final Map<Long, Map<OkrAncestors.OkrType, ReportQuotaChangeRequest.Goal>> goalHierarchyByRequestId = new HashMap<>();

    private final boolean showGoalQuestions;
    private final boolean showGoalHierarchy;

    public ReportRequestCollector(final boolean showGoalQuestions, final boolean showGoalHierarchy) {
        this.showGoalQuestions = showGoalQuestions;
        this.showGoalHierarchy = showGoalHierarchy;
    }

    @Override
    protected void processFirstRequestRow(final @NotNull ResultSet rs, final long requestId) throws SQLException {
        super.processFirstRequestRow(rs, requestId);

        if (showGoalQuestions) {
            final PGobject requestGoalAnswers = (PGobject) rs.getObject("request_goal_answers");

            if (requestGoalAnswers != null) {
                final Map<Long, String> requestGoalAnswersMap = SqlUtils.fromJsonb(requestGoalAnswers, REQUEST_GOAL_ANSWERS_TYPE);
                requestGoalAnswersByRequestId.put(requestId, requestGoalAnswersMap);
            }
        }

        if (showGoalHierarchy) {
            final Map<OkrAncestors.OkrType, ReportQuotaChangeRequest.Goal> goalByType = new EnumMap<>(OkrAncestors.OkrType.class);
            final Long valueStreamGoalId = SqlDaoBase.getLong(rs, "goal_value_stream_goal_id");

            if (valueStreamGoalId != null) {
                goalByType.put(OkrAncestors.OkrType.VALUE_STREAM, new ReportQuotaChangeRequest.Goal(valueStreamGoalId, rs.getString("okr_vs_name")));
            }
            final Long umbrellaGoalId = SqlDaoBase.getLong(rs, "goal_umbrella_goal_id");
            if (umbrellaGoalId != null) {
                goalByType.put(OkrAncestors.OkrType.UMBRELLA, new ReportQuotaChangeRequest.Goal(umbrellaGoalId, rs.getString("okr_umb_name")));
            }

            final Long contourGoalId = SqlDaoBase.getLong(rs, "goal_contour_goal_id");
            if (contourGoalId != null) {
                goalByType.put(OkrAncestors.OkrType.CONTOUR, new ReportQuotaChangeRequest.Goal(contourGoalId, rs.getString("okr_con_name")));
            }

            goalHierarchyByRequestId.put(requestId, goalByType);
        }
    }

    @Nonnull
    @Override
    public Stream<ReportQuotaChangeRequest> get() {
        return requestsBuilders.stream()
                .map(builder -> {
                    final QuotaChangeRequest request = builder.build();
                    final Map<Long, String> requestGoalAnswers = requestGoalAnswersByRequestId.getOrDefault(request.getId(), Collections.emptyMap());
                    return new ReportQuotaChangeRequest(request, requestGoalAnswers, goalHierarchyByRequestId.getOrDefault(request.getId(), Collections.emptyMap()));
                });
    }
}
