/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.cassandra.diff.api.services;

import java.io.Closeable;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Function;


import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.datastax.driver.core.*;
import com.datastax.driver.core.utils.UUIDs;
import org.apache.cassandra.diff.ClusterProvider;
import org.apache.cassandra.diff.JobConfiguration;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Days;

// TODO cache jobsummary
// TODO fix exception handling
public class DBService implements Closeable {
    private static final Logger logger = LoggerFactory.getLogger(DBService.class);
    private static final long QUERY_TIMEOUT_MS = 3000;

    private final Cluster cluster;
    private final Session session;
    private final String diffKeyspace;

    private final PreparedStatement runningJobsStatement;
    private final PreparedStatement jobSummaryStatement;
    private final PreparedStatement jobResultStatement;
    private final PreparedStatement jobStatusStatement;
    private final PreparedStatement jobMismatchesStatement;
    private final PreparedStatement jobErrorSummaryStatement;
    private final PreparedStatement jobErrorRangesStatement;
    private final PreparedStatement jobErrorDetailStatement;
    private final PreparedStatement jobsStartDateStatement;
    private final PreparedStatement jobsForSourceStatement;
    private final PreparedStatement jobsForTargetStatement;
    private final PreparedStatement jobsForKeyspaceStatement;

    public DBService(JobConfiguration config) {
        logger.info("Initializing DBService");
        ClusterProvider provider = ClusterProvider.getProvider(config.clusterConfig("metadata"), "metadata");
        cluster = provider.getCluster();

        session = cluster.connect();
        diffKeyspace = config.metadataOptions().keyspace;
        runningJobsStatement = session.prepare(String.format(
            " SELECT job_id " +
            " FROM %s.running_jobs", diffKeyspace));
        jobSummaryStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id," +
            "   job_start_time," +
            "   buckets," +
            "   keyspace_name, " +
            "   table_names, " +
            "   source_cluster_name," +
            "   source_cluster_desc," +
            "   target_cluster_name," +
            "   target_cluster_desc," +
            "   total_tasks " +
            " FROM %s.job_summary" +
            " WHERE job_id = ?", diffKeyspace));
        jobResultStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id," +
            "   table_name, " +
            "   matched_partitions," +
            "   mismatched_partitions,"   +
            "   matched_rows,"   +
            "   matched_values,"   +
            "   mismatched_values,"   +
            "   partitions_only_in_source,"   +
            "   partitions_only_in_target,"   +
            "   skipped_partitions"   +
            " FROM %s.job_results" +
            " WHERE job_id = ? AND table_name = ?", diffKeyspace));
        jobStatusStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id,"   +
            "   bucket,"   +
            "   table_name,"   +
            "   completed "   +
            " FROM %s.job_status" +
            " WHERE job_id = ? AND bucket = ?", diffKeyspace));
        jobMismatchesStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id," +
            "   bucket," +
            "   table_name," +
            "   mismatching_token," +
            "   mismatch_type" +
            " FROM %s.mismatches" +
            " WHERE job_id = ? AND bucket = ?", diffKeyspace));
        jobErrorSummaryStatement = session.prepare(String.format(
            " SELECT " +
            "   count(start_token) AS error_count," +
            "   table_name" +
            " FROM %s.task_errors" +
            " WHERE job_id = ? AND bucket = ?",
            diffKeyspace));
        jobErrorRangesStatement = session.prepare(String.format(
            " SELECT " +
            "   bucket,"   +
            "   table_name,"   +
            "   start_token,"   +
            "   end_token"   +
            " FROM %s.task_errors" +
            " WHERE job_id = ? AND bucket = ?",
            diffKeyspace));
        jobErrorDetailStatement = session.prepare(String.format(
            " SELECT " +
            "   table_name,"   +
            "   error_token"   +
            " FROM %s.partition_errors" +
            " WHERE job_id = ? AND bucket = ? AND table_name = ? AND start_token = ? AND end_token = ?", diffKeyspace));
        jobsStartDateStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id" +
            " FROM %s.job_start_index" +
            " WHERE job_start_date = ? AND job_start_hour = ?", diffKeyspace));
        jobsForSourceStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id" +
            " FROM %s.source_cluster_index" +
            " WHERE source_cluster_name = ?", diffKeyspace));
        jobsForTargetStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id" +
            " FROM %s.target_cluster_index" +
            " WHERE target_cluster_name = ?", diffKeyspace));
        jobsForKeyspaceStatement = session.prepare(String.format(
            " SELECT " +
            "   job_id" +
            " FROM %s.keyspace_index" +
            " WHERE keyspace_name = ?", diffKeyspace));
    }

    public List<UUID> fetchRunningJobs() {
        List<UUID> jobs = new ArrayList<>();
        ResultSet rs = session.execute(runningJobsStatement.bind());
        rs.forEach(row -> jobs.add(row.getUUID("job_id")));
        return jobs;
    }

    public Collection<JobSummary> fetchJobSummaries(List<UUID> jobIds) {
        List<ResultSetFuture> futures = Lists.newArrayListWithCapacity(jobIds.size());
        jobIds.forEach(id -> futures.add(session.executeAsync(jobSummaryStatement.bind(id))));

        // Oldest first
        SortedSet<JobSummary> summaries = Sets.newTreeSet(JobSummary.COMPARATOR);
        processFutures(futures, JobSummary::fromRow, summaries::add);
        return summaries;
    }

    public JobSummary fetchJobSummary(UUID jobId) {
        Row row = session.execute(jobSummaryStatement.bind(jobId)).one();
        if (row == null)
            throw new RuntimeException(String.format("Job %s not found", jobId));
        return JobSummary.fromRow(row);
    }

    public Collection<JobResult> fetchJobResults(UUID jobId) {
        JobSummary summary = fetchJobSummary(jobId);
        List<ResultSetFuture> futures = Lists.newArrayListWithCapacity(summary.tables.size());
        for (String table : summary.tables)
            futures.add(session.executeAsync(jobResultStatement.bind(jobId, table)));

        SortedSet<JobResult> results = Sets.newTreeSet();
        processFutures(futures, JobResult::fromRow, results::add);
        return results;
    }

    public JobStatus fetchJobStatus(UUID jobId) {
        JobSummary summary = fetchJobSummary(jobId);
        List<ResultSetFuture> futures = Lists.newArrayListWithCapacity(summary.buckets);

        for (int i = 0; i < summary.buckets; i++)
            futures.add(session.executeAsync(jobStatusStatement.bind(jobId, i)));

        Map<String, Long> completedByTable = Maps.newHashMapWithExpectedSize(summary.tables.size());
        processFutures(futures, row -> completedByTable.merge(row.getString("table_name"),
                                                              row.getLong("completed"),
                                                              Long::sum));
        return new JobStatus(jobId, completedByTable);
    }

    public JobMismatches fetchMismatches(UUID jobId) {
        JobSummary summary = fetchJobSummary(jobId);
        List<ResultSetFuture> futures = Lists.newArrayListWithCapacity(summary.buckets);

        for (int i = 0; i < summary.buckets; i++)
            futures.add(session.executeAsync(jobMismatchesStatement.bind(jobId, i)));

        Map<String, List<Mismatch>> mismatchesByTable = Maps.newHashMapWithExpectedSize(summary.tables.size());
        processFutures(futures, row -> mismatchesByTable.merge(row.getString("table_name"),
                                                               Lists.newArrayList(new Mismatch(row.getString("mismatching_token"),
                                                                                               row.getString("mismatch_type"))),
                                                               (l1, l2) -> { l1.addAll(l2); return l1;}));
        return new JobMismatches(jobId, mismatchesByTable);
    }

    public JobErrorSummary fetchErrorSummary(UUID jobId) {
        JobSummary summary = fetchJobSummary(jobId);
        List<ResultSetFuture> futures = Lists.newArrayListWithCapacity(summary.buckets);

        for (int i = 0; i < summary.buckets; i++)
            futures.add(session.executeAsync(jobErrorSummaryStatement.bind(jobId, i)));

        Map<String, Long> errorCountByTable = Maps.newHashMapWithExpectedSize(summary.tables.size());
        processFutures(futures, row -> {
            String table = row.getString("table_name");
            if (null != table) {
                errorCountByTable.merge(row.getString("table_name"),
                                        row.getLong("error_count"),
                                        Long::sum);
            }
        });
        return new JobErrorSummary(jobId, errorCountByTable);
    }

    public JobErrorRanges fetchErrorRanges(UUID jobId) {
        JobSummary summary = fetchJobSummary(jobId);
        List<ResultSetFuture> futures = Lists.newArrayListWithCapacity(summary.buckets);

        for (int i = 0; i < summary.buckets; i++)
            futures.add(session.executeAsync(jobErrorRangesStatement.bind(jobId, i)));

        Map<String, List<Range>> errorRangesByTable = Maps.newHashMapWithExpectedSize(summary.tables.size());
        processFutures(futures, row -> errorRangesByTable.merge(row.getString("table_name"),
                                                                Lists.newArrayList(new Range(row.getString("start_token"),
                                                                                             row.getString("end_token"))),
                                                                (l1, l2) -> { l1.addAll(l2); return l1;}));
        return new JobErrorRanges(jobId, errorRangesByTable);
    }

    public JobErrorDetail fetchErrorDetail(UUID jobId) {
        JobSummary summary = fetchJobSummary(jobId);
        List<ResultSetFuture> rangeFutures = Lists.newArrayListWithCapacity(summary.buckets);

        for (int i = 0; i < summary.buckets; i++ )
            rangeFutures.add(session.executeAsync(jobErrorRangesStatement.bind(jobId, i)));

        List<ResultSetFuture> errorFutures = Lists.newArrayList();
        processFutures(rangeFutures,
                       row -> session.executeAsync(jobErrorDetailStatement.bind(jobId,
                                                                                row.getInt("bucket"),
                                                                                row.getString("table_name"),
                                                                                row.getString("start_token"),
                                                                                row.getString("end_token"))),
                       errorFutures::add);
        Map<String, List<String>> errorsByTable = Maps.newHashMapWithExpectedSize(summary.tables.size());
        processFutures(errorFutures,
                       row -> errorsByTable.merge(row.getString("table_name"),
                                                  Lists.newArrayList(row.getString("error_token")),
                                                  (l1, l2) -> { l1.addAll(l2); return l1;}));
        return new JobErrorDetail(jobId, errorsByTable);
    }

    public Collection<JobSummary> fetchJobsStartedBetween(DateTime start, DateTime end) {
        int days = Days.daysBetween(start, end).getDays();
        List<ResultSetFuture> idFutures = Lists.newArrayListWithCapacity(days * 24);
        for (int i = 0; i <= days; i++) {
            DateTime date = start.plusDays(i);
            LocalDate ld = LocalDate.fromYearMonthDay(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth());
            for (int j = 0; j <= 23; j++) {
                idFutures.add(session.executeAsync(jobsStartDateStatement.bind(ld, j)));
            }
        }

        List<ResultSetFuture> jobFutures = Lists.newArrayList();
        processFutures(idFutures,
                       row -> session.executeAsync(jobSummaryStatement.bind(row.getUUID("job_id"))),
                       jobFutures::add);

        SortedSet<JobSummary> jobs = Sets.newTreeSet(JobSummary.COMPARATOR.reversed());
        processFutures(jobFutures, JobSummary::fromRow, jobs::add);
        return jobs;
    }

    public Collection<JobSummary> fetchJobsForSourceCluster(String sourceClusterName) {
        ResultSet jobIds = session.execute(jobsForSourceStatement.bind(sourceClusterName));
        List<ResultSetFuture> futures = Lists.newArrayList();
        jobIds.forEach(row -> futures.add(session.executeAsync(jobSummaryStatement.bind(row.getUUID("job_id")))));


        SortedSet<JobSummary> jobs = Sets.newTreeSet(JobSummary.COMPARATOR.reversed());
        processFutures(futures, JobSummary::fromRow, jobs::add);
        return jobs;
    }

    public Collection<JobSummary> fetchJobsForTargetCluster(String targetClusterName) {
        ResultSet jobIds = session.execute(jobsForTargetStatement.bind(targetClusterName));
        List<ResultSetFuture> futures = Lists.newArrayList();
        jobIds.forEach(row -> futures.add(session.executeAsync(jobSummaryStatement.bind(row.getUUID("job_id")))));

        // most recent first
        SortedSet<JobSummary> jobs = Sets.newTreeSet(JobSummary.COMPARATOR.reversed());
        processFutures(futures, JobSummary::fromRow, jobs::add);
        return jobs;
    }

    public Collection<JobSummary> fetchJobsForKeyspace(String keyspace) {
        ResultSet jobIds = session.execute(jobsForKeyspaceStatement.bind(keyspace));
        List<ResultSetFuture> futures = Lists.newArrayList();
        jobIds.forEach(row -> futures.add(session.executeAsync(jobSummaryStatement.bind(row.getUUID("job_id")))));

        // most recent first
        SortedSet<JobSummary> jobs = Sets.newTreeSet(JobSummary.COMPARATOR.reversed());
        processFutures(futures, JobSummary::fromRow, jobs::add);
        return jobs;
    }

    private void processFutures(List<ResultSetFuture> futures, Consumer<Row> consumer) {
        processFutures(futures, Function.identity(), consumer);
    }

    private <T> void processFutures(List<ResultSetFuture> futures, Function<Row, T> transform, Consumer<T> consumer) {
        Consumer<ResultSet> resultConsumer = resultSet -> resultSet.forEach(row -> consumer.accept(transform.apply(row)));
        futures.forEach(f -> getResultsSafely(f).ifPresent(resultConsumer));
    }

    private Optional<ResultSet> getResultsSafely(ResultSetFuture future) {
        try {
            return Optional.ofNullable(future.get(QUERY_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } catch (Exception e) {
            logger.warn("Error getting result from async query", e);
            return Optional.empty();
        }
    }

    public void close()
    {
        session.close();
        cluster.close();
    }

    public static class Range {
        final String start;
        final String end;

        public Range(String start, String end) {
            this.start = start;
            this.end = end;
        }
    }

    public static class JobErrorSummary {
        final UUID jobId;
        final Map<String, Long> errorsByTable;

        public JobErrorSummary(UUID jobId, Map<String, Long> errorsByTable) {
            this.jobId = jobId;
            this.errorsByTable = errorsByTable;
        }
    }

    public static class JobErrorRanges {
        final UUID jobId;
        final Map<String, List<Range>> rangesByTable;

        public JobErrorRanges(UUID jobId, Map<String, List<Range>> rangesByTable) {
            this.jobId = jobId;
            this.rangesByTable = rangesByTable;
        }
    }

    public static class JobErrorDetail {
        final UUID jobId;
        final Map<String, List<String>> errorsByTable;

        public JobErrorDetail(UUID jobId, Map<String, List<String>> errorsByTable) {
            this.jobId = jobId;
            this.errorsByTable = errorsByTable;
        }
    }

    public static class JobMismatches {

        final UUID jobId;
        final Map<String, List<Mismatch>> mismatchesByTable;

        public JobMismatches(UUID jobId, Map<String, List<Mismatch>> mismatchesByTable) {
            this.jobId = jobId;
            this.mismatchesByTable = mismatchesByTable;
        }
    }

    public static class Mismatch {
        final String token;
        final String type;

        public Mismatch(String token, String type) {
            this.token = token;
            this.type = type;
        }
    }

    public static class JobStatus {

        final UUID jobId;
        final Map<String, Long> completedByTable;

        public JobStatus(UUID jobId, Map<String, Long> completedByTable) {
            this.jobId = jobId;
            this.completedByTable = completedByTable;
        }
    }

    public static class JobResult implements Comparable<JobResult> {

        final UUID jobId;
        final String table;
        final long matchedPartitions;
        final long mismatchedPartitions;
        final long matchedRows;
        final long matchedValues;
        final long mismatchedValues;
        final long onlyInSource;
        final long onlyInTarget;
        final long skippedPartitions;

        public JobResult(UUID jobId,
                         String table,
                         long matchedPartitions,
                         long mismatchedPartitions,
                         long matchedRows,
                         long matchedValues,
                         long mismatchedValues,
                         long onlyInSource,
                         long onlyInTarget,
                         long skippedPartitions) {
            this.jobId = jobId;
            this.table = table;
            this.matchedPartitions = matchedPartitions;
            this.mismatchedPartitions = mismatchedPartitions;
            this.matchedRows = matchedRows;
            this.matchedValues = matchedValues;
            this.mismatchedValues = mismatchedValues;
            this.onlyInSource = onlyInSource;
            this.onlyInTarget = onlyInTarget;
            this.skippedPartitions = skippedPartitions;
        }

        static JobResult fromRow(Row row) {
            return new JobResult(row.getUUID("job_id"),
                                 row.getString("table_name"),
                                 row.getLong("matched_partitions"),
                                 row.getLong("mismatched_partitions"),
                                 row.getLong("matched_rows"),
                                 row.getLong("matched_values"),
                                 row.getLong("mismatched_values"),
                                 row.getLong("partitions_only_in_source"),
                                 row.getLong("partitions_only_in_target"),
                                 row.getLong("skipped_partitions"));
        }

        public int compareTo(@NotNull JobResult other) {
            return this.table.compareTo(other.table);
        }
    }

    public static class JobSummary {

        public static final Comparator<JobSummary> COMPARATOR = Comparator.comparing(j -> j.startTime);

        final UUID jobId;
        final int buckets;
        final String keyspace;
        final List<String> tables;
        final String sourceClusterName;
        final String sourceClusterDesc;
        final String targetClusterName;
        final String targetClusterDesc;
        final int tasks;
        final String start;

        // private so it isn't included in json serialization
        private final DateTime startTime;

        private JobSummary(UUID jobId,
                           DateTime startTime,
                           int buckets,
                           String keyspace,
                           List<String> tables,
                           String sourceClusterName,
                           String sourceClusterDesc,
                           String targetClusterName,
                           String targetClusterDesc,
                           int tasks)
        {
            this.jobId = jobId;
            this.startTime = startTime;
            this.start = startTime.toString();
            this.buckets = buckets;
            this.keyspace = keyspace;
            this.tables = tables;
            this.sourceClusterName = sourceClusterName;
            this.sourceClusterDesc = sourceClusterDesc;
            this.targetClusterName = targetClusterName;
            this.targetClusterDesc = targetClusterDesc;
            this.tasks = tasks;
        }

        static JobSummary fromRow(Row row) {
            return new JobSummary(row.getUUID("job_id"),
                                  new DateTime(UUIDs.unixTimestamp(row.getUUID("job_start_time")), DateTimeZone.UTC),
                                  row.getInt("buckets"),
                                  row.getString("keyspace_name"),
                                  row.getList("table_names", String.class),
                                  row.getString("source_cluster_name"),
                                  row.getString("source_cluster_desc"),
                                  row.getString("target_cluster_name"),
                                  row.getString("target_cluster_desc"),
                                  row.getInt("total_tasks"));
        }
    }
}
