// 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.

#include <stdint.h>

#include <memory>
#include <string>

#include <gtest/gtest.h>

#include "kudu/client/client.h"
#include "kudu/client/scan_batch.h"
#include "kudu/client/schema.h"
#include "kudu/client/shared_ptr.h" // IWYU pragma: keep
#include "kudu/client/write_op.h"
#include "kudu/common/partial_row.h"
#include "kudu/integration-tests/external_mini_cluster-itest-base.h"
#include "kudu/util/slice.h"
#include "kudu/util/status.h"
#include "kudu/util/test_macros.h"

using std::unique_ptr;

namespace kudu {
namespace client {

using sp::shared_ptr;

class VarcharItest : public ExternalMiniClusterITestBase {
 protected:
  void SetUp() override {
    NO_FATALS(StartCluster({}, {}, kNumServers));
  }

  const int kNumServers = 3;
  const int kNumTablets = 3;
  const char* const kTableName = "varchar-table";
};

TEST_F(VarcharItest, TestVarcharTruncation) {
  KuduSchemaBuilder builder;
  builder.AddColumn("key")->Type(KuduColumnSchema::INT64)
    ->NotNull()->PrimaryKey();
  builder.AddColumn("value")->Type(KuduColumnSchema::VARCHAR)
    ->Length(10);
  KuduSchema schema;
  ASSERT_OK(builder.Build(&schema));

  // Create table
  unique_ptr<client::KuduTableCreator> table_creator(client_->NewTableCreator());
  ASSERT_OK(table_creator->table_name(kTableName)
      .schema(&schema)
      .num_replicas(kNumServers)
      .add_hash_partitions({ "key" }, kNumTablets)
      .Create());
  shared_ptr<KuduTable> table;
  ASSERT_OK(client_->OpenTable(kTableName, &table));

  // Insert row with long varchar values to test the truncation happens properly
  shared_ptr<KuduSession> session = client_->NewSession();
  ASSERT_OK(session->SetFlushMode(KuduSession::AUTO_FLUSH_BACKGROUND));
  KuduInsert* insert = table->NewInsert();
  KuduPartialRow* write = insert->mutable_row();

  ASSERT_OK(write->SetInt64("key", 1));
  ASSERT_OK(write->SetVarchar("value", "foobar         baz"));
  ASSERT_OK(session->Apply(insert));
  ASSERT_OK(session->Flush());

  // Read rows
  KuduScanner scanner(table.get());
  ASSERT_OK(scanner.SetFaultTolerant());
  ASSERT_OK(scanner.Open());
  while (scanner.HasMoreRows()) {
    KuduScanBatch batch;
    ASSERT_OK(scanner.NextBatch(&batch));
    for (const KuduScanBatch::RowPtr& read : batch) {
      int64_t key;
      ASSERT_OK(read.GetInt64("key", &key));
      ASSERT_EQ(1, key);
      Slice value;
      ASSERT_OK(read.GetVarchar("value", &value));
      ASSERT_EQ("foobar    ", value);
    }
  }
}

TEST_F(VarcharItest, TestInvalidLength) {
  KuduSchemaBuilder builder;
  builder.AddColumn("key")->Type(KuduColumnSchema::INT64)
    ->NotNull()->PrimaryKey();
  builder.AddColumn("value")->Type(KuduColumnSchema::VARCHAR)
    ->Length(0);
  KuduSchema schema;
  Status s = builder.Build(&schema);
  ASSERT_FALSE(s.ok());
}

TEST_F(VarcharItest, TestVarcharRangePartition) {
  KuduSchemaBuilder builder;
  builder.AddColumn("key")->Type(KuduColumnSchema::VARCHAR)
    ->Length(10)->NotNull()->PrimaryKey();
  builder.AddColumn("value")->Type(KuduColumnSchema::VARCHAR)
    ->Length(10);
  KuduSchema schema;
  ASSERT_OK(builder.Build(&schema));

  KuduPartialRow* lower_bound = schema.NewRow();
  ASSERT_OK(lower_bound->SetVarchar("key", "bar"));
  KuduPartialRow* upper_bound = schema.NewRow();
  ASSERT_OK(upper_bound->SetVarchar("key", "foo"));

  unique_ptr<client::KuduTableCreator> table_creator(client_->NewTableCreator());
  ASSERT_OK(table_creator->table_name(kTableName)
      .schema(&schema)
      .num_replicas(kNumServers)
      .set_range_partition_columns({ "key" })
      .add_range_partition(lower_bound, upper_bound)
      .Create());
  shared_ptr<KuduTable> table;
  ASSERT_OK(client_->OpenTable(kTableName, &table));

  shared_ptr<KuduSession> session = client_->NewSession();
  ASSERT_OK(session->SetFlushMode(KuduSession::AUTO_FLUSH_BACKGROUND));
  KuduInsert* insert = table->NewInsert();
  KuduPartialRow* write = insert->mutable_row();

  ASSERT_OK(write->SetVarchar("key", "baz"));
  ASSERT_OK(write->SetVarchar("value", "foobar"));
  ASSERT_OK(session->Apply(insert));
  ASSERT_OK(session->Flush());

  KuduScanner scanner(table.get());
  ASSERT_OK(scanner.SetFaultTolerant());
  ASSERT_OK(scanner.Open());
  ASSERT_TRUE(scanner.HasMoreRows());
  while (scanner.HasMoreRows()) {
    KuduScanBatch batch;
    ASSERT_OK(scanner.NextBatch(&batch));
    for (const KuduScanBatch::RowPtr& read : batch) {
      Slice key;
      ASSERT_OK(read.GetVarchar("key", &key));
      ASSERT_EQ("baz", key);
      Slice value;
      ASSERT_OK(read.GetVarchar("value", &value));
      ASSERT_EQ("foobar", value);
    }
  }
}

} // namespace client
} // namespace kudu
