/*
 * 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 "iggy.hpp"

namespace iggy {

namespace {

rust::Vec<ffi::HeaderEntry> ToFfiRawOptions(const std::map<std::string, std::string> &raw_options) {
    rust::Vec<ffi::HeaderEntry> ffi_options;
    ffi_options.reserve(raw_options.size());
    for (const auto &[key, value] : raw_options) {
        ffi::HeaderEntry ffi_entry;
        ffi_entry.key.kind = static_cast<std::uint8_t>(HeaderKind::String);
        ffi_entry.key.value.reserve(key.size());
        for (const char character : key) {
            ffi_entry.key.value.push_back(static_cast<std::uint8_t>(character));
        }
        ffi_entry.value.kind = static_cast<std::uint8_t>(HeaderKind::String);
        ffi_entry.value.value.reserve(value.size());
        for (const char character : value) {
            ffi_entry.value.value.push_back(static_cast<std::uint8_t>(character));
        }
        ffi_options.push_back(std::move(ffi_entry));
    }
    return ffi_options;
}

template <typename FfiOptions, typename Options>
void SetMutableTopicOptions(FfiOptions &ffi_options, const Options &options) {
    if (const auto &value = options.CompressionAlgorithm()) {
        ffi_options.has_compression_algorithm = true;
        ffi_options.compression_algorithm     = std::string(value->Value());
    }
    if (const auto &value = options.MessageExpiry()) {
        ffi_options.has_message_expiry   = true;
        ffi_options.message_expiry_kind  = std::string(value->Kind());
        ffi_options.message_expiry_value = value->Value();
    }
    if (const auto &value = options.MaxTopicSize()) {
        ffi_options.has_max_topic_size = true;
        ffi_options.max_topic_size     = std::string(value->Value());
    }
    ffi_options.raw_options = ToFfiRawOptions(options.RawEntries());
}

}  // namespace

IggyBlockingClient::IggyBlockingClient(IggyBlockingClient &&other) noexcept
    : client_(std::exchange(other.client_, nullptr)) {}

IggyBlockingClient &IggyBlockingClient::operator=(IggyBlockingClient &&other) noexcept {
    if (this != &other) {
        Reset();
        client_ = std::exchange(other.client_, nullptr);
    }
    return *this;
}

IggyBlockingClient::~IggyBlockingClient() {
    Reset();
}

IggyBlockingClient IggyBlockingClient::FromConnectionString(std::string connection_string) {
    return RethrowAsIggyException(
        [&connection_string] { return IggyBlockingClient(ffi::from_connection_string(connection_string)); });
}

void IggyBlockingClient::Connect() {
    RethrowAsIggyException([this] { Handle()->connect(); });
}

void IggyBlockingClient::Disconnect() {
    RethrowAsIggyException([this] { Handle()->disconnect(); });
}

void IggyBlockingClient::Shutdown() {
    RethrowAsIggyException([this] { Handle()->shutdown(); });
}

LoginInfo IggyBlockingClient::Login(std::string username, std::string password) {
    return RethrowAsIggyException(
        [this, &username, &password] { return LoginInfo::FromFfi(Handle()->login_user(username, password)); });
}

void IggyBlockingClient::Logout() {
    RethrowAsIggyException([this] { Handle()->logout_user(); });
}

UserInfoDetails IggyBlockingClient::GetUser(const Identifier &user) {
    return RethrowAsIggyException([this, &user] { return UserInfoDetails::FromFfi(Handle()->get_user(user.ToFfi())); });
}

std::vector<UserInfo> IggyBlockingClient::GetUsers() {
    return RethrowAsIggyException([this] {
        std::vector<UserInfo> users;
        auto ffi_users = Handle()->get_users();
        users.reserve(ffi_users.size());
        for (auto &user : ffi_users) {
            users.push_back(UserInfo::FromFfi(std::move(user)));
        }
        return users;
    });
}

UserInfoDetails IggyBlockingClient::CreateUser(std::string username,
                                               std::string password,
                                               UserStatus status,
                                               const std::optional<Permissions> &permissions) {
    return RethrowAsIggyException([this, &username, &password, status, &permissions] {
        auto ffi_permissions = permissions ? permissions->ToFfi() : ffi::Permissions{};
        return UserInfoDetails::FromFfi(Handle()->create_user(username, password, static_cast<ffi::UserStatus>(status),
                                                              permissions.has_value(), std::move(ffi_permissions)));
    });
}

void IggyBlockingClient::DeleteUser(const Identifier &user) {
    RethrowAsIggyException([this, &user] { Handle()->delete_user(user.ToFfi()); });
}

void IggyBlockingClient::UpdateUser(const Identifier &user,
                                    const std::optional<std::string> username,
                                    const std::optional<UserStatus> status,
                                    const UserUpdateOptions &options) {
    RethrowAsIggyException([this, &user, &username, status, &options] {
        auto ffi_options = ToFfiRawOptions(options.RawEntries());
        Handle()->update_user(user.ToFfi(), username.has_value(), username.value_or(""), status.has_value(),
                              static_cast<ffi::UserStatus>(status.value_or(UserStatus::Active)),
                              std::move(ffi_options));
    });
}

StreamDetails IggyBlockingClient::CreateStream(std::string name) {
    return RethrowAsIggyException([this, &name] { return StreamDetails::FromFfi(Handle()->create_stream(name)); });
}

void IggyBlockingClient::UpdateStream(const Identifier &stream, std::string name, const StreamUpdateOptions &options) {
    RethrowAsIggyException([this, &stream, &name, &options] {
        auto ffi_options = ToFfiRawOptions(options.RawEntries());
        Handle()->update_stream(stream.ToFfi(), name, std::move(ffi_options));
    });
}

std::vector<Stream> IggyBlockingClient::GetStreams() {
    return RethrowAsIggyException([this] {
        std::vector<Stream> streams;
        auto ffi_streams = Handle()->get_streams();
        streams.reserve(ffi_streams.size());
        for (auto &stream : ffi_streams) {
            streams.push_back(Stream::FromFfi(std::move(stream)));
        }
        return streams;
    });
}

StreamDetails IggyBlockingClient::GetStream(const Identifier &stream) {
    return RethrowAsIggyException(
        [this, &stream] { return StreamDetails::FromFfi(Handle()->get_stream(stream.ToFfi())); });
}

void IggyBlockingClient::DeleteStream(const Identifier &stream) {
    RethrowAsIggyException([this, &stream] { Handle()->delete_stream(stream.ToFfi()); });
}

void IggyBlockingClient::PurgeStream(const Identifier &stream) {
    RethrowAsIggyException([this, &stream] { Handle()->purge_stream(stream.ToFfi()); });
}

TopicDetails IggyBlockingClient::CreateTopic(const Identifier &stream,
                                             std::string name,
                                             const TopicCreateOptions &options) {
    return RethrowAsIggyException([this, &stream, &name, &options] {
        ffi::TopicCreateOptions ffi_options{};
        SetMutableTopicOptions(ffi_options, options);
        if (auto value = options.PartitionsCount()) {
            ffi_options.has_partitions_count = true;
            ffi_options.partitions_count     = *value;
        } else {
            ffi_options.has_partitions_count = false;
            ffi_options.partitions_count     = 0;
        }
        if (auto value = options.SegmentSize()) {
            ffi_options.has_segment_size = true;
            ffi_options.segment_size     = *value;
        } else {
            ffi_options.has_segment_size = false;
            ffi_options.segment_size     = 0;
        }
        if (auto value = options.Durability()) {
            ffi_options.has_durability = true;
            ffi_options.durability     = std::string(iggy::to_string(*value));
        } else {
            ffi_options.has_durability = false;
            ffi_options.durability     = "";
        }
        if (auto value = options.ConsumerOffsetDurability()) {
            ffi_options.has_consumer_offset_durability = true;
            ffi_options.consumer_offset_durability     = std::string(iggy::to_string(*value));
        } else {
            ffi_options.has_consumer_offset_durability = false;
            ffi_options.consumer_offset_durability     = "";
        }
        if (auto value = options.MessagesRequiredToSave()) {
            ffi_options.has_messages_required_to_save = true;
            ffi_options.messages_required_to_save     = *value;
        } else {
            ffi_options.has_messages_required_to_save = false;
            ffi_options.messages_required_to_save     = 0;
        }
        if (auto value = options.SizeOfMessagesRequiredToSave()) {
            ffi_options.has_size_of_messages_required_to_save = true;
            ffi_options.size_of_messages_required_to_save     = *value;
        } else {
            ffi_options.has_size_of_messages_required_to_save = false;
            ffi_options.size_of_messages_required_to_save     = 0;
        }
        if (auto value = options.PreallocateSegments()) {
            ffi_options.has_preallocate_segments = true;
            ffi_options.preallocate_segments     = *value;
        } else {
            ffi_options.has_preallocate_segments = false;
            ffi_options.preallocate_segments     = false;
        }
        return TopicDetails::FromFfi(Handle()->create_topic(stream.ToFfi(), name, std::move(ffi_options)));
    });
}

void IggyBlockingClient::UpdateTopic(const Identifier &stream,
                                     const Identifier &topic,
                                     std::string name,
                                     const TopicUpdateOptions &options) {
    RethrowAsIggyException([this, &stream, &topic, &name, &options] {
        ffi::TopicUpdateOptions ffi_options{};
        SetMutableTopicOptions(ffi_options, options);

        Handle()->update_topic(stream.ToFfi(), topic.ToFfi(), name, std::move(ffi_options));
    });
}

std::vector<Topic> IggyBlockingClient::GetTopics(const Identifier &stream) {
    return RethrowAsIggyException([this, &stream] {
        std::vector<Topic> topics;
        auto ffi_topics = Handle()->get_topics(stream.ToFfi());
        topics.reserve(ffi_topics.size());
        for (auto &topic : ffi_topics) {
            topics.push_back(Topic::FromFfi(std::move(topic)));
        }
        return topics;
    });
}

TopicDetails IggyBlockingClient::GetTopic(const Identifier &stream, const Identifier &topic) {
    return RethrowAsIggyException(
        [this, &stream, &topic] { return TopicDetails::FromFfi(Handle()->get_topic(stream.ToFfi(), topic.ToFfi())); });
}

void IggyBlockingClient::DeleteTopic(const Identifier &stream, const Identifier &topic) {
    RethrowAsIggyException([this, &stream, &topic] { Handle()->delete_topic(stream.ToFfi(), topic.ToFfi()); });
}

void IggyBlockingClient::PurgeTopic(const Identifier &stream, const Identifier &topic) {
    RethrowAsIggyException([this, &stream, &topic] { Handle()->purge_topic(stream.ToFfi(), topic.ToFfi()); });
}

void IggyBlockingClient::CreatePartitions(const Identifier &stream,
                                          const Identifier &topic,
                                          const std::uint32_t partitions_count) {
    RethrowAsIggyException([this, &stream, &topic, partitions_count] {
        Handle()->create_partitions(stream.ToFfi(), topic.ToFfi(), partitions_count);
    });
}

void IggyBlockingClient::DeletePartitions(const Identifier &stream,
                                          const Identifier &topic,
                                          const std::uint32_t partitions_count) {
    RethrowAsIggyException([this, &stream, &topic, partitions_count] {
        Handle()->delete_partitions(stream.ToFfi(), topic.ToFfi(), partitions_count);
    });
}

void IggyBlockingClient::DeleteSegments(const Identifier &stream,
                                        const Identifier &topic,
                                        const std::uint32_t partition_id,
                                        const std::uint32_t segments_count) {
    RethrowAsIggyException([this, &stream, &topic, partition_id, segments_count] {
        Handle()->delete_segments(stream.ToFfi(), topic.ToFfi(), partition_id, segments_count);
    });
}

ConsumerGroupDetails IggyBlockingClient::CreateConsumerGroup(const Identifier &stream,
                                                             const Identifier &topic,
                                                             std::string name) {
    return RethrowAsIggyException([this, &stream, &topic, &name] {
        return ConsumerGroupDetails::FromFfi(Handle()->create_consumer_group(stream.ToFfi(), topic.ToFfi(), name));
    });
}

ConsumerGroupDetails IggyBlockingClient::GetConsumerGroup(const Identifier &stream,
                                                          const Identifier &topic,
                                                          const Identifier &group) {
    return RethrowAsIggyException([this, &stream, &topic, &group] {
        return ConsumerGroupDetails::FromFfi(
            Handle()->get_consumer_group(stream.ToFfi(), topic.ToFfi(), group.ToFfi()));
    });
}

std::vector<ConsumerGroup> IggyBlockingClient::GetConsumerGroups(const Identifier &stream, const Identifier &topic) {
    return RethrowAsIggyException([this, &stream, &topic] {
        std::vector<ConsumerGroup> groups;
        auto ffi_groups = Handle()->get_consumer_groups(stream.ToFfi(), topic.ToFfi());
        groups.reserve(ffi_groups.size());
        for (auto &group : ffi_groups) {
            groups.push_back(ConsumerGroup::FromFfi(std::move(group)));
        }
        return groups;
    });
}

void IggyBlockingClient::DeleteConsumerGroup(const Identifier &stream,
                                             const Identifier &topic,
                                             const Identifier &group) {
    RethrowAsIggyException([this, &stream, &topic, &group] {
        Handle()->delete_consumer_group(stream.ToFfi(), topic.ToFfi(), group.ToFfi());
    });
}

void IggyBlockingClient::JoinConsumerGroup(const Identifier &stream, const Identifier &topic, const Identifier &group) {
    RethrowAsIggyException([this, &stream, &topic, &group] {
        Handle()->join_consumer_group(stream.ToFfi(), topic.ToFfi(), group.ToFfi());
    });
}

void IggyBlockingClient::LeaveConsumerGroup(const Identifier &stream,
                                            const Identifier &topic,
                                            const Identifier &group) {
    RethrowAsIggyException([this, &stream, &topic, &group] {
        Handle()->leave_consumer_group(stream.ToFfi(), topic.ToFfi(), group.ToFfi());
    });
}

void IggyBlockingClient::StoreConsumerOffset(const Consumer &consumer,
                                             const Identifier &stream,
                                             const Identifier &topic,
                                             const std::optional<std::uint32_t> partition_id,
                                             const std::uint64_t offset) {
    RethrowAsIggyException([this, &consumer, &stream, &topic, offset, partition_id] {
        constexpr auto unspecified_partition_id = std::numeric_limits<std::uint32_t>::max();
        if (partition_id == unspecified_partition_id) {
            throw std::invalid_argument("partition_id cannot be the maximum std::uint32_t value");
        }
        const auto ffi_partition_id = partition_id.value_or(unspecified_partition_id);
        Handle()->store_consumer_offset(stream.ToFfi(), topic.ToFfi(), ffi_partition_id,
                                        std::string(consumer.KindName()), consumer.Id().ToFfi(), offset);
    });
}

ConsumerOffsetInfo IggyBlockingClient::GetConsumerOffset(const Consumer &consumer,
                                                         const Identifier &stream,
                                                         const Identifier &topic,
                                                         const std::optional<std::uint32_t> partition_id) {
    return RethrowAsIggyException([this, &consumer, &stream, &topic, partition_id] {
        constexpr auto unspecified_partition_id = std::numeric_limits<std::uint32_t>::max();
        if (partition_id == unspecified_partition_id) {
            throw std::invalid_argument("partition_id cannot be the maximum std::uint32_t value");
        }
        const auto ffi_partition_id = partition_id.value_or(unspecified_partition_id);
        return ConsumerOffsetInfo::FromFfi(Handle()->get_consumer_offset(
            stream.ToFfi(), topic.ToFfi(), ffi_partition_id, std::string(consumer.KindName()), consumer.Id().ToFfi()));
    });
}

void IggyBlockingClient::DeleteConsumerOffset(const Consumer &consumer,
                                              const Identifier &stream,
                                              const Identifier &topic,
                                              const std::optional<std::uint32_t> partition_id) {
    RethrowAsIggyException([this, &consumer, &stream, &topic, partition_id] {
        constexpr auto unspecified_partition_id = std::numeric_limits<std::uint32_t>::max();
        if (partition_id == unspecified_partition_id) {
            throw std::invalid_argument("partition_id cannot be the maximum std::uint32_t value");
        }
        const auto ffi_partition_id = partition_id.value_or(unspecified_partition_id);
        Handle()->delete_consumer_offset(stream.ToFfi(), topic.ToFfi(), ffi_partition_id,
                                         std::string(consumer.KindName()), consumer.Id().ToFfi());
    });
}

ClientInfoDetails IggyBlockingClient::GetMe() {
    return RethrowAsIggyException([this] { return ClientInfoDetails::FromFfi(Handle()->get_me()); });
}

ClientInfoDetails IggyBlockingClient::GetClient(std::uint32_t client_id) {
    return RethrowAsIggyException(
        [this, client_id] { return ClientInfoDetails::FromFfi(Handle()->get_client(client_id)); });
}

std::vector<ClientInfo> IggyBlockingClient::GetClients() {
    return RethrowAsIggyException([this] {
        std::vector<ClientInfo> clients;
        auto ffi_clients = Handle()->get_clients();
        clients.reserve(ffi_clients.size());
        for (auto &client : ffi_clients) {
            clients.push_back(ClientInfo::FromFfi(std::move(client)));
        }
        return clients;
    });
}

void IggyBlockingClient::FlushUnsavedBuffer(const Identifier &stream,
                                            const Identifier &topic,
                                            const std::uint32_t partition_id,
                                            const bool fsync) {
    RethrowAsIggyException([this, &stream, &topic, partition_id, fsync] {
        Handle()->flush_unsaved_buffer(stream.ToFfi(), topic.ToFfi(), partition_id, fsync);
    });
}

Stats IggyBlockingClient::GetStats() {
    return RethrowAsIggyException([this] { return Stats::FromFfi(Handle()->get_stats()); });
}

IggyBlockingClient::IggyBlockingClient(ffi::Client *client) : client_(client) {
    if (client_ == nullptr) {
        throw IggyException("Could not create Iggy client");
    }
}

ffi::Client *IggyBlockingClient::Handle() const {
    if (client_ == nullptr) {
        throw IggyException("Cannot use a moved-from IggyBlockingClient");
    }
    return client_;
}

void IggyBlockingClient::Reset() noexcept {
    if (client_ == nullptr) {
        return;
    }

    ffi::Client *client{std::exchange(client_, nullptr)};
    ffi::delete_client(client);
}

IggyBlockingClient::Builder::Builder() = default;

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithServerAddress(std::string server_address) {
    if (server_address.empty()) {
        throw IggyException("Server address cannot be empty");
    }
    server_address_ = std::move(server_address);
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithAutoLogin(std::string username, std::string password) {
    if (username.empty() || password.empty()) {
        throw IggyException("Automatic login username and password cannot be empty");
    }
    auto_login_kind_     = ffi::AutoLoginKind::UsernamePassword;
    auto_login_username_ = std::move(username);
    auto_login_password_ = std::move(password);
    personal_access_token_.clear();
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithPersonalAccessToken(std::string token) {
    if (token.empty()) {
        throw IggyException("Personal access token cannot be empty");
    }
    auto_login_kind_       = ffi::AutoLoginKind::PersonalAccessToken;
    personal_access_token_ = std::move(token);
    auto_login_username_.clear();
    auto_login_password_.clear();
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithReconnectionMaxRetries(std::uint32_t retries) {
    reconnection_max_retries_ = retries;
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithoutReconnectionLimit() {
    reconnection_max_retries_.reset();
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithReconnectionInterval(std::chrono::microseconds interval) {
    if (interval.count() < 0) {
        throw IggyException("Reconnection interval cannot be negative");
    }
    reconnection_interval_micros_ = static_cast<std::uint64_t>(interval.count());
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithReestablishAfter(std::chrono::microseconds duration) {
    if (duration.count() < 0) {
        throw IggyException("Reestablish duration cannot be negative");
    }
    reestablish_after_micros_ = static_cast<std::uint64_t>(duration.count());
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithTlsEnabled(bool enabled) {
    tls_enabled_ = enabled;
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithTlsDomain(std::string domain) {
    if (domain.empty()) {
        throw IggyException("TLS domain cannot be empty");
    }
    tls_domain_ = std::move(domain);
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithTlsCaFile(std::string path) {
    if (path.empty()) {
        throw IggyException("TLS CA file cannot be empty");
    }
    tls_ca_file_ = std::move(path);
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithTlsCertificateValidation(bool enabled) {
    tls_validate_certificate_ = enabled;
    return *this;
}

IggyBlockingClient::Builder &IggyBlockingClient::Builder::WithNoDelay() {
    no_delay_ = true;
    return *this;
}

IggyBlockingClient IggyBlockingClient::Builder::Build() const {
    return IggyBlockingClient::RethrowAsIggyException([this] {
        ffi::IggyClientConfig config{};
        config.server_address               = server_address_;
        config.auto_login_kind              = auto_login_kind_;
        config.username                     = auto_login_username_;
        config.password                     = auto_login_password_;
        config.personal_access_token        = personal_access_token_;
        config.has_reconnection_max_retries = reconnection_max_retries_.has_value();
        config.reconnection_max_retries     = reconnection_max_retries_.value_or(0);
        config.has_reconnection_interval    = reconnection_interval_micros_.has_value();
        config.reconnection_interval_micros = reconnection_interval_micros_.value_or(0);
        config.has_reestablish_after        = reestablish_after_micros_.has_value();
        config.reestablish_after_micros     = reestablish_after_micros_.value_or(0);
        config.tls_enabled                  = tls_enabled_;
        config.tls_domain                   = tls_domain_;
        config.tls_ca_file                  = tls_ca_file_;
        config.has_tls_validate_certificate = tls_validate_certificate_.has_value();
        config.tls_validate_certificate     = tls_validate_certificate_.value_or(false);
        config.no_delay                     = no_delay_;
        return IggyBlockingClient(ffi::new_connection(std::move(config)));
    });
}

}  // namespace iggy
