#pragma once

#include <balancer/kernel/process/config_check.h>
#include <balancer/kernel/process/base_process.h>
#include <balancer/kernel/process/listener.h>
#include <balancer/kernel/process/master_main.h>
#include <balancer/kernel/process/messages.h>
#include <balancer/kernel/process/worker_connection_callback.h>

#include <balancer/kernel/log/logbackend.h>
#include <balancer/kernel/process_common/fixed_buffer_io.h>
#include <balancer/kernel/process/children_common/process_stat.h>
#include <balancer/kernel/process/children_common/worker_schedule_callback.h>

#include <util/thread/factory.h>


namespace NSrvKernel::NProcessCore {
    class TDnsHelper;

    class TWorkerProcess
        : public TBaseProcess
    {
    public:
        TWorkerProcess(TMainTask& task, const TMainOptions& options, size_t workerId,
                       TW2WChannel<TM2CMessage>& m2cChannel, TW2WChannel<TC2MMessage>& c2mChannel);
        ~TWorkerProcess() override;

        void DoDispose() noexcept override;
        void DumpSharedFiles(NJson::TJsonWriter& out) override;
        void AddGracefulShutdownHandler(IGracefulShutdownHandler* handler, bool isHTTP2) override;
        void ShutDown(const TGracefulShutdownOpts& opts) noexcept;
        void Execute() override;
        void ResetDnsCacheEvent();
        void UpdateStateAfterCleanupMaster() noexcept;
        void ReportChildReadyAfterConfigReload(TCont*) noexcept;
        void SendMasterMessage(TC2MMessage message, TInstant deadLine);
        void FuncExecution();
        void CallEvent(TEventData& event, bool jsonOut) const noexcept;
        bool Finished() const noexcept {
            return Finished_;
        }

        void AddAccepted(const TAddrDescr& addr);
        void AddCanceled(const TAddrDescr& addr);

        TSharedFiles* SharedFiles() noexcept override;
        TThreadedQueue* ThreadedQueue(const TString& name) noexcept override;
        IPingerManager& SharedPingerManager() noexcept override;
        TLog* GetLog(const TString& name) override;
        TLog* GetDynamicBalancingLog() override;
        NProcessCore::TChildProcessType WorkerType() const noexcept override;
        NDns::IResolver& Resolver() noexcept final;
        TContExecutor& Executor() const noexcept override {
            return WorkerExecutor_->Executor();
        }

        void RegisterBackendGroup(TString id, IModule* mod) noexcept override {
            BackendGroups_.emplace_back(id, mod);
        }

        bool IsBanned(const NAddr::IRemoteAddr& addr) const noexcept;

        const TMainConfig& MainConfig() const noexcept;

    private:
        void InitThreadedResolver(); // DNS resolving
        void InitThreadedLogs();
        void InitThreadedStuff();
        void MemoryPrealloc();
        void CloseListeners(const TGracefulShutdownOpts& opts) noexcept override;
        void GracefulShutdownLoop(const TGracefulShutdownOpts opts) noexcept;
        void RunRequestProcessor();
        void RecvLoop();

    private:
        class TListenersAndCallbacks {
        public:
            explicit TListenersAndCallbacks(TWorkerProcess* process);
            void Start(TContExecutor& executor);
            TError CloseUsingBPF();
            void Destroy();
            [[nodiscard]] bool ListenersExists() const;

        private:
            TDeque<TListener> ListenerCallbacks_;
            TDeque<TOwnListener> Listeners_;
        };

    public:
        TContextSafeLog<TSystemLog> Log_;
        THolder<TMainStats> MainStats_;
    private:
        THolder<TWorkerCpuStat> WorkerCpuStat_;
        THolder<TWorkerScheduleCallback> WorkerScheduleCallback_;
    public:
        THolder<TOwnExecutor> WorkerExecutor_;
        THolder<TCpuLimiter> CpuLimiter_;
        TIntrusiveList<TConnection> Connections_;
    private:
        using TAcceptedStats = THashMap<TAddrDescr, ui64, TAddrDescrOps, TAddrDescrOps>;
        TAcceptedStats Accepted_;
        TAcceptedStats Canceled_;

        THolder<NDns::TStatsCounters> DnsCounters_;
        bool Finished_ = false;

        IThreadFactory* ThreadPool_ = SystemThreadFactory();
        TThreadedQueueList ThreadedQueueList_;
        TContextSafeLog<TSystemLog> PingerLog_;
        TContextSafeLog<TSystemLog> DynamicBalancingLog_;
        THashMap<TString, TSimpleSharedPtr<TContextSafeLog<TLog>>> Logs_;
        TIntrusiveList<IGracefulShutdownHandler> GracefulShutdownHandlers_;
        TIntrusiveList<IGracefulShutdownHandler> GracefulShutdownHTTP2Handlers_;

        TCoroutine CpuMeasureCoroutine_;
        TCoroutine GracefulShutdownCoroutine_;
        TCoroutine FuncExecutionCont_;
        TCoroutine RequestProcessor_;
        TCoroutine RecvLoopTask_;

        TW2WChannel<TM2CMessage>& M2CChannel_;
        TW2WChannel<TC2MMessage>& C2MChannel_;

        TListenersAndCallbacks Listeners_;
        THolder<NDns::THelper> DnsHelper_;

        TVector<TBackendGroup> BackendGroups_;
        THolder<TCoroutine> ConfigCheckTask_;

        TSharedFileExistsChecker BanAddressesDisableFileChecker_;
    };
}
