/*
 * 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,
                                    std::optional<std::string> username,
                                    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()); });
}

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;
            switch (*value) {
                case Durability::Replicated:
                    ffi_options.durability = "replicated";
                    break;
                case Durability::Persisted:
                    ffi_options.durability = "persisted";
                    break;
                default:
                    throw std::invalid_argument("Unknown durability");
            }
        } else {
            ffi_options.has_durability = false;
            ffi_options.durability     = "";
        }
        if (auto value = options.ConsumerOffsetDurability()) {
            ffi_options.has_consumer_offset_durability = true;
            switch (*value) {
                case Durability::Replicated:
                    ffi_options.consumer_offset_durability = "replicated";
                    break;
                case Durability::Persisted:
                    ffi_options.consumer_offset_durability = "persisted";
                    break;
                default:
                    throw std::invalid_argument("Unknown consumer offset durability");
            }
        } 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::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, consumer.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, consumer.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, consumer.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;
    });
}

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

SendMessagesResponse IggyBlockingClient::SendMessages(const Identifier &stream,
                                                      const Identifier &topic,
                                                      const Partitioning &partitioning,
                                                      const std::vector<IggyMessageToSend> &messages) {
    return RethrowAsIggyException([this, &stream, &topic, &partitioning, &messages] {
        rust::Vec<ffi::IggyMessageToSend> ffi_messages;
        ffi_messages.reserve(messages.size());
        for (const auto &message : messages) {
            ffi_messages.push_back(message.ToFfi());
        }
        rust::Vec<std::uint8_t> ffi_partitioning_value;
        ffi_partitioning_value.reserve(partitioning.Value().size());
        for (const auto byte : partitioning.Value()) {
            ffi_partitioning_value.push_back(byte);
        }
        return SendMessagesResponse::FromFfi(
            Handle()->send_messages(stream.ToFfi(), topic.ToFfi(), std::string(partitioning.Kind()),
                                    std::move(ffi_partitioning_value), std::move(ffi_messages)));
    });
}

PolledMessages IggyBlockingClient::PollMessages(const Identifier &stream,
                                                const Identifier &topic,
                                                const std::optional<std::uint32_t> partition_id,
                                                const Consumer &consumer,
                                                const PollingStrategy &strategy,
                                                const std::uint32_t count,
                                                const bool auto_commit) {
    return RethrowAsIggyException([this, &stream, &topic, partition_id, &consumer, &strategy, count, auto_commit] {
        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 PolledMessages::FromFfi(Handle()->poll_messages(stream.ToFfi(), topic.ToFfi(), ffi_partition_id,
                                                               consumer.ToFfi(), std::string(strategy.Kind()),
                                                               strategy.Value(), count, auto_commit));
    });
}

std::vector<OptionSpec> IggyBlockingClient::DescribeOptions(std::string scope) {
    return RethrowAsIggyException([this, &scope] {
        std::vector<OptionSpec> specs;
        auto ffi_specs = Handle()->describe_options(scope);
        specs.reserve(ffi_specs.size());
        for (auto &spec : ffi_specs) {
            specs.push_back(OptionSpec::FromFfi(std::move(spec)));
        }
        return specs;
    });
}

void IggyBlockingClient::Ping() {
    RethrowAsIggyException([this] { Handle()->ping(); });
}

std::chrono::microseconds IggyBlockingClient::HeartbeatInterval() {
    return RethrowAsIggyException([this] { return std::chrono::microseconds(Handle()->heartbeat_interval()); });
}

std::vector<std::uint8_t> IggyBlockingClient::Snapshot(const SnapshotCompression &compression,
                                                       const std::vector<SystemSnapshotType> &types) {
    return RethrowAsIggyException([this, &compression, &types] {
        rust::Vec<rust::String> ffi_types;
        ffi_types.reserve(types.size());
        for (const auto &snapshot_type : types) {
            ffi_types.push_back(rust::String(std::string(snapshot_type.SnapshotTypeValue())));
        }
        auto ffi_snapshot = Handle()->snapshot(std::string(compression.Value()), std::move(ffi_types));
        return std::vector<std::uint8_t>(ffi_snapshot.begin(), ffi_snapshot.end());
    });
}

std::vector<std::uint8_t> IggyBlockingClient::SendBinaryRequest(std::uint32_t code,
                                                                const std::vector<std::uint8_t> &payload) {
    return RethrowAsIggyException([this, code, &payload] {
        rust::Vec<std::uint8_t> ffi_payload;
        ffi_payload.reserve(payload.size());
        for (const auto byte : payload) {
            ffi_payload.push_back(byte);
        }
        auto ffi_response = Handle()->send_binary_request(code, std::move(ffi_payload));
        return std::vector<std::uint8_t>(ffi_response.begin(), ffi_response.end());
    });
}

void IggyBlockingClient::UpdatePermissions(const Identifier &user, const std::optional<Permissions> &permissions) {
    RethrowAsIggyException([this, &user, &permissions] {
        auto ffi_permissions = permissions ? permissions->ToFfi() : ffi::Permissions{};
        Handle()->update_permissions(user.ToFfi(), permissions.has_value(), std::move(ffi_permissions));
    });
}

void IggyBlockingClient::ChangePassword(const Identifier &user,
                                        std::string current_password,
                                        std::string new_password) {
    RethrowAsIggyException([this, &user, &current_password, &new_password] {
        Handle()->change_password(user.ToFfi(), current_password, new_password);
    });
}

ClusterMetadata IggyBlockingClient::GetClusterMetadata() {
    return RethrowAsIggyException([this] { return ClusterMetadata::FromFfi(Handle()->get_cluster_metadata()); });
}

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
