/*
 * Copyright 2023 CeresDB Project Authors. Licensed under Apache-2.0.
 */
package io.ceresdb;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

import io.ceresdb.common.Display;
import io.ceresdb.common.Endpoint;
import io.ceresdb.common.Lifecycle;
import io.ceresdb.common.VisibleForTest;
import io.ceresdb.common.util.Clock;
import io.ceresdb.common.util.MetricsUtil;
import io.ceresdb.common.util.Requires;
import io.ceresdb.common.util.SerializingExecutor;
import io.ceresdb.common.util.Spines;
import io.ceresdb.common.util.Strings;
import io.ceresdb.errors.StreamException;
import io.ceresdb.limit.LimitedPolicy;
import io.ceresdb.limit.WriteLimiter;
import io.ceresdb.models.Err;
import io.ceresdb.models.Point;
import io.ceresdb.models.RequestContext;
import io.ceresdb.models.Result;
import io.ceresdb.models.Value;
import io.ceresdb.models.WriteOk;
import io.ceresdb.models.WriteRequest;
import io.ceresdb.options.WriteOptions;
import io.ceresdb.proto.internal.Storage;
import io.ceresdb.rpc.Context;
import io.ceresdb.rpc.Observer;
import io.ceresdb.util.StreamWriteBuf;
import io.ceresdb.util.Utils;

import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.google.common.collect.Lists;

/**
 * Default Write API impl.
 *
 */
public class WriteClient implements Write, Lifecycle<WriteOptions>, Display {

    private static final Logger LOG = LoggerFactory.getLogger(WriteClient.class);

    private WriteOptions opts;
    private RouterClient routerClient;
    private Executor     asyncPool;
    private WriteLimiter writeLimiter;

    static final class InnerMetrics {
        static final Histogram WRITE_POINTS_SUCCESS = MetricsUtil.histogram("write_points_success_num");
        static final Histogram WRITE_POINTS_FAILED  = MetricsUtil.histogram("write_points_failed_num");
        static final Histogram POINTS_NUM_PER_WRITE = MetricsUtil.histogram("points_num_per_write");
        static final Meter     WRITE_FAILED         = MetricsUtil.meter("write_failed");
        static final Meter     WRITE_QPS            = MetricsUtil.meter("write_qps");

        static Histogram writePointsSuccess() {
            return WRITE_POINTS_SUCCESS;
        }

        static Histogram writePointsFailed() {
            return WRITE_POINTS_FAILED;
        }

        static Histogram pointsNumPerWrite() {
            return POINTS_NUM_PER_WRITE;
        }

        static Meter writeFailed() {
            return WRITE_FAILED;
        }

        static Meter writeQps() {
            return WRITE_QPS;
        }

        static Meter writeByRetries(final int retries) {
            // more than 3 retries are classified as the same metric
            return MetricsUtil.meter("write_by_retries", Math.min(3, retries));
        }
    }

    @Override
    public boolean init(final WriteOptions opts) {
        this.opts = Requires.requireNonNull(opts, "WriteClient.opts");
        this.routerClient = this.opts.getRoutedClient();
        final Executor pool = this.opts.getAsyncPool();
        this.asyncPool = pool != null ? pool : new SerializingExecutor("write_client");
        this.writeLimiter = new DefaultWriteLimiter(this.opts.getMaxInFlightWritePoints(),
                this.opts.getLimitedPolicy());
        return true;
    }

    @Override
    public void shutdownGracefully() {
        // NO-OP
    }

    @Override
    public CompletableFuture<Result<WriteOk, Err>> write(final WriteRequest req, final Context ctx) {
        req.setReqCtx(attachRequestCtx(req.getReqCtx()));

        Requires.requireTrue(Strings.isNotBlank(req.getReqCtx().getDatabase()), "No database selected");
        Requires.requireNonNull(req.getPoints(), "Null.data");

        final long startCall = Clock.defaultClock().getTick();
        return this.writeLimiter.acquireAndDo(req.getPoints(),
                () -> write0(req.getReqCtx(), req.getPoints(), ctx, 0).whenCompleteAsync((r, e) -> {
                    InnerMetrics.writeQps().mark();
                    if (r != null) {
                        if (Utils.isRwLogging()) {
                            LOG.info("Write to {}, duration={} ms, result={}.", Utils.DB_NAME,
                                    Clock.defaultClock().duration(startCall), r);
                        }
                        if (r.isOk()) {
                            final WriteOk ok = r.getOk();
                            InnerMetrics.writePointsSuccess().update(ok.getSuccess());
                            InnerMetrics.writePointsFailed().update(ok.getFailed());
                            return;
                        }
                    }
                    InnerMetrics.writeFailed().mark();
                }, this.asyncPool));
    }

    @Override
    public StreamWriteBuf<Point, WriteOk> streamWrite(final RequestContext reqCtx, final String table,
                                                      final Context ctx) {
        final RequestContext finalReqCtx = attachRequestCtx(reqCtx);

        Requires.requireTrue(Strings.isNotBlank(finalReqCtx.getDatabase()), "No database selected");
        Requires.requireTrue(Strings.isNotBlank(table), "Blank.table");

        final CompletableFuture<WriteOk> respFuture = new CompletableFuture<>();

        return this.routerClient.routeFor(finalReqCtx, Collections.singleton(table))
                .thenApply(routes -> routes.values().stream().findFirst().orElseGet(() -> Route.invalid(table)))
                .thenApply(route -> streamWriteTo(route, finalReqCtx, ctx, Utils.toUnaryObserver(respFuture)))
                .thenApply(reqObserver -> new StreamWriteBuf<Point, WriteOk>() {

                    private final List<Point> buf = Spines.newBuf();

                    @Override
                    public StreamWriteBuf<Point, WriteOk> write(final Point val) {
                        this.buf.add(val);
                        return this;
                    }

                    @Override
                    public StreamWriteBuf<Point, WriteOk> write(final Collection<Point> c) {
                        this.buf.addAll(c);
                        return this;
                    }

                    @Override
                    public StreamWriteBuf<Point, WriteOk> flush() {
                        if (respFuture.isCompletedExceptionally()) {
                            respFuture.getNow(null); // throw the exception now
                        }
                        if (!this.buf.isEmpty()) {
                            reqObserver.onNext(this.buf.stream());
                            this.buf.clear();
                        }
                        return this;
                    }

                    @Override
                    public StreamWriteBuf<Point, WriteOk> writeAndFlush(final Collection<Point> c) {
                        flush(); // flush the previous write
                        reqObserver.onNext(c.stream());
                        return this;
                    }

                    @Override
                    public CompletableFuture<WriteOk> completed() {
                        flush();
                        reqObserver.onCompleted();
                        return respFuture;
                    }
                }).join();
    }

    private RequestContext attachRequestCtx(RequestContext reqCtx) {
        if (reqCtx == null) {
            reqCtx = new RequestContext();
        }
        if (Strings.isNullOrEmpty(reqCtx.getDatabase())) {
            reqCtx.setDatabase(this.opts.getDatabase());
        }
        return reqCtx;
    }

    private CompletableFuture<Result<WriteOk, Err>> write0(final RequestContext reqCtx, final List<Point> data, //
                                                           final Context ctx, //
                                                           final int retries) {
        InnerMetrics.writeByRetries(retries).mark();

        final Set<String> tables = data.stream() //
                .map(Point::getTable) //
                .collect(Collectors.toSet());

        InnerMetrics.pointsNumPerWrite().update(tables.size());

        // 1. Get routes
        return this.routerClient.routeFor(reqCtx, tables)
                // 2. Split data by route info and write to DB
                .thenComposeAsync(routes -> Utils.splitDataByRoute(data, routes).entrySet().stream()
                        // Write to database
                        .map(e -> writeTo(e.getKey(), reqCtx, e.getValue(), ctx.copy(), retries))
                        // Reduce and combine write result
                        .reduce((f1, f2) -> f1.thenCombineAsync(f2, Utils::combineResult, this.asyncPool))
                        .orElse(Utils.completedCf(WriteOk.emptyOk().mapToResult())), this.asyncPool)
                // 3. If failed, refresh route info and retry on INVALID_ROUTE
                .thenComposeAsync(r -> {
                    if (r.isOk()) {
                        LOG.debug("Success to write to {}, ok={}.", Utils.DB_NAME, r.getOk());
                        return Utils.completedCf(r);
                    }

                    final Err err = r.getErr();
                    LOG.warn("Failed to write to {}, err={}.", Utils.DB_NAME, err);

                    // Should refresh route table
                    final Set<String> toRefresh = err.stream() //
                            .filter(Utils::shouldRefreshRouteTable) //
                            .flatMap(e -> e.getFailedWrites().stream()) //
                            .map(Point::getTable) //
                            .collect(Collectors.toSet());
                    this.routerClient.clearRouteCacheBy(toRefresh);

                    // Should retry
                    final List<Point> pointsToRetry = err.stream() //
                            .filter(Utils::shouldRetry) //
                            .flatMap(e -> e.getFailedWrites().stream()) //
                            .collect(Collectors.toList());
                    if (pointsToRetry.isEmpty()) {
                        return Utils.completedCf(r);
                    }

                    if (retries + 1 > this.opts.getMaxRetries()) {
                        LOG.error("Retried {} times still failed.", retries);
                        return Utils.completedCf(r);
                    }

                    final CompletableFuture<Result<WriteOk, Err>> rwf = this.routerClient.routeFor(reqCtx, toRefresh)
                            // Even for some data that does not require a refresh of the routing table,
                            // we still wait until the routing table is flushed successfully before
                            // retrying it, in order to give the server a break.
                            .thenComposeAsync(routes -> write0(reqCtx, pointsToRetry, ctx, retries + 1),
                                    this.asyncPool);

                    // Should not retry
                    final Optional<Err> noRetryErr = err.stream() //
                            .filter(Utils::shouldNotRetry) //
                            .reduce(Err::combine);
                    return noRetryErr.isPresent() ?
                            rwf.thenApplyAsync(ret -> Utils.combineResult(noRetryErr.get().mapToResult(), ret),
                                    this.asyncPool) :
                            rwf.thenApplyAsync(ret -> Utils.combineResult(err.getSubOk().mapToResult(), ret),
                                    this.asyncPool);
                }, this.asyncPool);
    }

    private CompletableFuture<Result<WriteOk, Err>> writeTo(final Endpoint endpoint, //
                                                            final RequestContext reqCtx, //
                                                            final List<Point> data, //
                                                            final Context ctx, //
                                                            final int retries) {
        // The cost is worth it
        final int rowCount = data.size();
        final int maxWriteSize = this.opts.getMaxWriteSize();
        if (rowCount <= maxWriteSize) {
            return writeTo0(endpoint, reqCtx, data, ctx, retries);
        }

        final Stream.Builder<CompletableFuture<Result<WriteOk, Err>>> fs = Stream.builder();

        for (List<Point> part : Lists.partition(data, maxWriteSize)) {
            fs.add(writeTo0(endpoint, reqCtx, part, ctx.copy(), retries));
        }

        return fs.build() //
                .reduce((f1, f2) -> f1.thenCombineAsync(f2, Utils::combineResult, this.asyncPool)) //
                .orElse(Utils.completedCf(WriteOk.emptyOk().mapToResult()));
    }

    private CompletableFuture<Result<WriteOk, Err>> writeTo0(final Endpoint endpoint, //
                                                             final RequestContext reqCtx, //
                                                             final List<Point> data, //
                                                             final Context ctx, //
                                                             final int retries) {
        final CompletableFuture<Storage.WriteResponse> wrf = this.routerClient.invoke(endpoint, //
                toWriteRequestObj(reqCtx, data.stream()), //
                ctx.with("retries", retries) // server can use this in metrics
        );

        return wrf.thenApplyAsync(resp -> Utils.toResult(resp, endpoint, data), this.asyncPool);
    }

    private Observer<Stream<Point>> streamWriteTo(final Route route, //
                                                  final RequestContext reqCtx, //
                                                  final Context ctx, //
                                                  final Observer<WriteOk> respObserver) {
        final Observer<Storage.WriteRequest> rpcObs = this.routerClient.invokeClientStreaming(route.getEndpoint(), //
                Storage.WriteRequest.getDefaultInstance(), //
                ctx, //
                new Observer<Storage.WriteResponse>() {

                    @Override
                    public void onNext(final Storage.WriteResponse value) {
                        final Result<WriteOk, Err> ret = Utils.toResult(value, route.getEndpoint(), null);
                        if (ret.isOk()) {
                            respObserver.onNext(ret.getOk());
                        } else {
                            respObserver.onError(new StreamException("Failed to do stream write: " + ret.getErr()));
                        }
                    }

                    @Override
                    public void onError(final Throwable err) {
                        respObserver.onError(err);
                    }

                    @Override
                    public void onCompleted() {
                        respObserver.onCompleted();
                    }
                });

        return new Observer<Stream<Point>>() {

            private final String table = route.getTable();

            @Override
            public void onNext(final Stream<Point> value) {
                final Stream<Point> data = value.filter(point -> {
                    if (this.table.equals(point.getTable())) {
                        return true;
                    }
                    throw new StreamException(
                            String.format("Invalid table %s, only can write %s.", point.getTable(), this.table));
                });

                rpcObs.onNext(toWriteRequestObj(reqCtx, data));
            }

            @Override
            public void onError(final Throwable err) {
                rpcObs.onError(err);
            }

            @Override
            public void onCompleted() {
                rpcObs.onCompleted();
            }
        };
    }

    private static class NameDict {
        private final Map<String, Integer> nameIndexes = new HashMap<>();
        private int                        index       = 0;

        public int insert(final String name) {
            return this.nameIndexes.computeIfAbsent(name, s -> this.index++);
        }

        public Iterable<String> toOrdered() {
            final String[] arr = new String[this.index];
            this.nameIndexes.forEach((name, i) -> arr[i] = name);

            return () -> new Iterator<String>() {

                private int index = 0;

                @Override
                public boolean hasNext() {
                    return this.index < arr.length;
                }

                @Override
                public String next() {
                    return arr[this.index++];
                }
            };
        }
    }

    private static class WriteTuple3 {
        String                                        table;
        Map<String, Storage.WriteSeriesEntry.Builder> seriesBuilders;
        NameDict                                      tagDict;
        NameDict                                      fieldDict;

        public WriteTuple3(String table) {
            this.table = table;
            this.seriesBuilders = new HashMap<>();
            this.tagDict = new NameDict();
            this.fieldDict = new NameDict();
        }

        public Map<String, Storage.WriteSeriesEntry.Builder> getSeriesBuilders() {
            return seriesBuilders;
        }

        public NameDict getTagDict() {
            return tagDict;
        }

        public NameDict getFieldDict() {
            return fieldDict;
        }

        public Storage.WriteTableRequest build() {
            Storage.WriteTableRequest.Builder writeTableRequest = Storage.WriteTableRequest.newBuilder()
                    .setTable(table);

            seriesBuilders.forEach((key, builder) -> {
                writeTableRequest.addEntries(builder.build());
            });

            return writeTableRequest //
                    .addAllTagNames(this.tagDict.toOrdered()) //
                    .addAllFieldNames(this.fieldDict.toOrdered()) //
                    .build();
        }
    }

    @VisibleForTest
    public Storage.WriteRequest toWriteRequestObj(final RequestContext reqCtx, final Stream<Point> data) {
        final Storage.WriteRequest.Builder writeRequestBuilder = Storage.WriteRequest.newBuilder();
        final Map<String, WriteTuple3> tuple3s = new HashMap<>();

        data.forEach(point -> {
            final String table = point.getTable();
            final WriteTuple3 tp3 = tuple3s.computeIfAbsent(table, WriteTuple3::new);

            final NameDict tagDict = tp3.getTagDict();
            point.getTags().forEach((tagK, tagV) -> {
                tagDict.insert(tagK);
            });
            StringBuffer seriesKeyBuffer = new StringBuffer();
            tagDict.toOrdered().forEach((tagK) -> {
                Value tagV = point.getTags().get(tagK);
                if (!Value.isNull(tagV)) {
                    seriesKeyBuffer.append(tagV.getObject().toString());
                }
            });
            Storage.WriteSeriesEntry.Builder seriesEntryBuilder = tp3.getSeriesBuilders()
                    .computeIfAbsent(seriesKeyBuffer.toString(), seriesKey -> {
                        final Storage.WriteSeriesEntry.Builder seBuilder = Storage.WriteSeriesEntry.newBuilder();
                        point.getTags().forEach((tagK, tagV) -> {
                            if (Value.isNull(tagV)) {
                                return;
                            }
                            final Storage.Tag.Builder tBui = Storage.Tag.newBuilder().setNameIndex(tagDict.insert(tagK))
                                    .setValue(Utils.toProtoValue(tagV));
                            seBuilder.addTags(tBui.build());
                        });
                        return seBuilder;
                    });

            final NameDict fieldDict = tp3.getFieldDict();
            final Storage.FieldGroup.Builder fgBui = Storage.FieldGroup.newBuilder().setTimestamp(point.getTimestamp());
            point.getFields().forEach((fieldK, fieldV) -> {
                if (Value.isNull(fieldV)) {
                    return;
                }
                final Storage.Field.Builder fBui = Storage.Field.newBuilder().setNameIndex(fieldDict.insert(fieldK))
                        .setValue(Utils.toProtoValue(fieldV));
                fgBui.addFields(fBui.build());
            });
            seriesEntryBuilder.addFieldGroups(fgBui.build());
        });

        Storage.RequestContext.Builder ctxBuilder = Storage.RequestContext.newBuilder();
        ctxBuilder.setDatabase(reqCtx.getDatabase());
        writeRequestBuilder.setContext(ctxBuilder.build());

        tuple3s.values().forEach(tp3 -> writeRequestBuilder.addTableRequests(tp3.build()));

        return writeRequestBuilder.build();
    }

    @Override
    public void display(final Printer out) {
        out.println("--- WriteClient ---") //
                .print("maxRetries=") //
                .println(this.opts.getMaxRetries()) //
                .print("maxWriteSize=") //
                .println(this.opts.getMaxWriteSize()) //
                .print("asyncPool=") //
                .println(this.asyncPool);
    }

    @Override
    public String toString() {
        return "WriteClient{" + //
               "opts=" + opts + //
               ", routerClient=" + routerClient + //
               ", asyncPool=" + asyncPool + //
               '}';
    }

    @VisibleForTest
    static class DefaultWriteLimiter extends WriteLimiter {

        public DefaultWriteLimiter(int maxInFlight, LimitedPolicy policy) {
            super(maxInFlight, policy, "write_limiter_acquire");
        }

        @Override
        public int calculatePermits(final List<Point> in) {
            return in == null ? 0 : in.size();
        }

        @Override
        public Result<WriteOk, Err> rejected(final List<Point> in, final RejectedState state) {
            final String errMsg = String.format(
                    "Write limited by client, acquirePermits=%d, maxPermits=%d, availablePermits=%d.", //
                    state.acquirePermits(), //
                    state.maxPermits(), //
                    state.availablePermits());
            return Result.err(Err.writeErr(Result.FLOW_CONTROL, errMsg, null, in));
        }
    }
}
