#pragma once

#include "shards_info.h"

#include <saas/api/action.h>
#include <saas/library/check_message/check_message.h>
#include <saas/library/persqueue/telemetry/telemetry.h>
#include <saas/library/sharding/sharding.h>
#include <kikimr/persqueue/sdk/deprecated/cpp/v2/persqueue.h>

#include <library/cpp/threading/atomic/bool.h>

#include <util/thread/pool.h>


namespace NSaas {

using TPQLibPtr = TAtomicSharedPtr<NPersQueue::TPQLib>;

class TPersQueueWriter;

class TPersQueueWriterSettings {
    friend class TPersQueueWriter;
public:
    TPersQueueWriterSettings() {
        CheckMessageSettings.SetDisabled(true);
    }

    TPersQueueWriterSettings& SetDryRun(bool value);

    TPersQueueWriterSettings& SetLogger(TIntrusivePtr<NPersQueue::ILogger>& logger);
    TPersQueueWriterSettings& SetPersQueueSettings(const TString& server, const TString& directoryWithTopics, NPersQueue::TPQLibSettings pqLibSettings = {});
    TPersQueueWriterSettings& SetPQLib(TPQLibPtr pqLib);
    TPersQueueWriterSettings& SetSourceIdPrefix(const TString& sourceIdPrefix);
    TPersQueueWriterSettings& SetCodec(NPersQueueCommon::ECodec codec);

    TPersQueueWriterSettings& SetServiceInfo(const TSearchMapInputSettings& searchMapSettings, const TString& service);
    TPersQueueWriterSettings& SetServiceInfo(const NSearchMapParser::TSearchMap& searchMap, const TString& service);
    TPersQueueWriterSettings& SetServiceInfo(const TVector<NSearchMapParser::TShardsInterval>& shards, const TShardsDispatcher::TContext& dispatching);

    TPersQueueWriterSettings& SetTvm(std::shared_ptr<NPersQueue::ICredentialsProvider> credentialsProvider);
    TPersQueueWriterSettings& SetTvm(std::shared_ptr<NTvmAuth::TTvmClient> tvmClient, const TString tvmAlias);
    TPersQueueWriterSettings& SetTvm(
        NTvmAuth::TTvmId srcClientId,
        NTvmAuth::TTvmId dstClientId,
        const TString& secret
    );
    TPersQueueWriterSettings& SetQloudTvm(
        NTvmAuth::TTvmId srcClientId,
        NTvmAuth::TTvmId dstClientId,
        ui32 port = 1
    );

    TPersQueueWriterSettings& SetMaxAttempts(ui32 maxAttempts);
    TPersQueueWriterSettings& SetConnectionTimeout(TDuration connectionTimeout);
    TPersQueueWriterSettings& SetSendTimeout(TDuration sendTimeout);
    TPersQueueWriterSettings& SetPrepareMessages(bool allow);
    TPersQueueWriterSettings& SetCheckMessagesSettings(const TCheckMessageSettings& settings);

    TPersQueueWriterSettings& SetThreadsBlockingMode(bool blocking);
    TPersQueueWriterSettings& SetWriteThreadsCount(ui64 threadsCount);
    TPersQueueWriterSettings& SetMaxInFlightCount(ui64 maxInFlightCount);
    TPersQueueWriterSettings& SetNoWriteQueue(bool value);
    TPersQueueWriterSettings& SetThreadsName(const TString& name);

    TPersQueueWriterSettings& SetTelemetryConfig(const TTelemetryConfig& config);
    TPersQueueWriterSettings& SetEnableTelemetry(const TDuration& interval = RECOMMENDED_TELEMETRY_INTERVAL);
    TPersQueueWriterSettings& SetUseLogbrokerCDS(const NPersQueue::EClusterDiscoveryUsageMode useLogBrokerCDS = NPersQueue::EClusterDiscoveryUsageMode::Use);

    bool IsCorrectlyFilled(TString* error) const;
    TString GetStringConfig() const;
    NJson::TJsonValue GetJsonConfig() const;

private:
    bool DryRun = false;

    TIntrusivePtr<NPersQueue::ILogger> Logger;
    TString Server;
    TString DirectoryWithTopics;
    NPersQueue::TPQLibSettings PQLibSettings;
    TPQLibPtr PQLib;
    TString SourceIdPrefix;
    std::optional<NPersQueueCommon::ECodec> Codec;

    TString ServiceName;
    std::optional<TSearchMapInputSettings> SearchMapSettings;
    std::optional<TServiceShards> ServiceShards;

    std::shared_ptr<NPersQueue::ICredentialsProvider> CredentialsProvider;

    ui32 MaxAttempts = 3;
    TDuration ConnectionTimeout = TDuration::Seconds(30);
    TDuration SendTimeout = TDuration::Seconds(30);
    bool PrepareMessages = true;

    TCheckMessageSettings CheckMessageSettings;

    bool ThreadsBlockingMode = false;
    ui64 ThreadsCount = 0;
    ui64 MaxInFlightCount = 0;
    bool NoWriteQueue = false;
    TString ThreadsName = "SaasPqWriter";

    std::optional<TTelemetryConfig> TelemetryConfig;
    std::optional<TDuration> TelemetryInterval;
    NPersQueue::EClusterDiscoveryUsageMode UseLogbrokerCDS = NPersQueue::EClusterDiscoveryUsageMode::Auto;
};

}
