#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_METRICS_SOFTWARE_METRICS_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_METRICS_SOFTWARE_METRICS_H_

#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "absl/base/no_destructor.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/synchronization/mutex.h"
#include "software_metrics_config.pb.h"
#include "resource.pb.h"
#include "software_metrics.pb.h"
#include "tlbmc/utils/command_executor.h"
#include "tlbmc/utils/shell_command_executor.h"

namespace milotic_tlbmc {

/*
The ss linux command is 'socketstats'.
-t displays only TCP sockets
-a displays all sockets (listening and non-listening)
-n displays numeric host names
This is piped into awk which does the following:
1. Skip the first line since it's just headers and we don't care about them
For each row after that:
2. Target column number 4 as part of the split command and cuts it into two
using the colon as a delimiter (Looks like ${IP}:${PORT})
3. Prints TCP socket state column (column 1 or $1 in the script) as well as the
last portion of the column 4 split in step 2 which happens to be the port.
*/
// clang-format off
/*
ss -tan output will be:

State     Recv-Q Send-Q               Local Address:Port                           Peer Address:Port
LISTEN    0      10                               *:23                                        *:*
LISTEN    0      4096                             *:22                                        *:*
TIME-WAIT 0      0      [2002:a05:613a:84d1:fd01::]:22                  [2001:4860:f803:3fe::b]:47104
ESTAB     0      0      [2002:a05:613a:84d1:fd01::]:443             [2002:a05:613a:84d1:1000::]:48022
*/
// clang-format on
/*
after being piped into the awk script becomes:
LISTEN 23
LISTEN 22
TIME-WAIT 22
ESTAB 443
*/

static const absl::NoDestructor<std::string> kSocketStatCmd(
    "ss -tan | awk 'NR > 1 { split($4, a, \":\"); print $1, a[length(a)] }'");

/*
The nft command is used to interact with the netfilter subsystem
list chain inet filter output displays all output chain rules
-j ensures the output is in JSON format
The JSON is then processed by the software_metrics object.

Example:
{
    "nftables": [
        {
            "metainfo": {
                "version": "1.0.9",
                "release_name": "Old Doc Yak #3",
                "json_schema_version": 1
            }
        },
        {
            "table": {
                "family": "inet",
                "name": "filter",
                "handle": 25
            }
        },
        {
            "rule": {
                "family": "inet",
                "table": "filter",
                "chain": "count_port_22",
                "handle": 18,
                "comment": "tcp-server-22-synack",
                "expr": [
                    {
                        "counter": {
                            "packets": 41,
                            "bytes": 3200
                        }
                    }
                ]
            }
        }
    ]
}
*/

static const absl::NoDestructor<std::string> kNetFilterCmd(
    "nft -j list table inet filter");

// Any implementation of this interface must be thread-safe regarding the listed
// functions.
class SoftwareMetrics {
 public:
  static absl::StatusOr<std::unique_ptr<SoftwareMetrics>> Create(
      const SoftwareMetricsConfig& config);

  static absl::StatusOr<std::unique_ptr<SoftwareMetrics>>
  CreateWithExecutorForUnitTest(
      const SoftwareMetricsConfig& config,
      absl::flat_hash_map<std::string, absl::StatusOr<std::string>>&);

  static SoftwareMetricsAttributesStatic CreateStaticAttributes(
      const SoftwareMetricsConfig& software_metrics_config);

  SoftwareMetricsValue GetSoftwareMetricsValues() const
      ABSL_LOCKS_EXCLUDED(metric_data_mutex_) {
    absl::MutexLock lock(&metric_data_mutex_);
    return values_;
  }

  virtual ~SoftwareMetrics() = default;

  SocketStatStates GetSocketStatStates() const
      ABSL_LOCKS_EXCLUDED(metric_data_mutex_) {
    absl::MutexLock lock(&metric_data_mutex_);
    return values_.socket_stat_state();
  }

  NetFilterStates GetNetFilterStates() const
      ABSL_LOCKS_EXCLUDED(metric_data_mutex_) {
    absl::MutexLock lock(&metric_data_mutex_);
    return values_.netfilter_state();
  }

  SoftwareMetricsAttributesDynamic GetSoftwareMetricsAttributesDynamic() const {
    absl::MutexLock lock(&metric_attributes_dynamic_mutex_);
    return metrics_attributes_dynamic_;
  }

  const SoftwareMetricsAttributesStatic& GetSoftwareMetricsAttributesStatic()
      const {
    return metrics_attributes_static_;
  }

  // Refreshes the metric data once asynchronously. The metric data will be
  // updated when the refresh is done.
  // The `callback` will be called when the refresh is done. The callback is
  // supposed to be blocking.
  void RefreshOnce(absl::AnyInvocable<void()> callback)
      ABSL_LOCKS_EXCLUDED(metric_data_mutex_);

  CommandExecutor* GetExecutorForTest() const {
    return executor_.get();
  }

 private:
  explicit SoftwareMetrics(
      const SoftwareMetricsAttributesStatic& software_attributes_static)
      : metrics_attributes_static_(software_attributes_static),
        ss_port_set_(metrics_attributes_static_.software_metrics_config()
                      .socket_stat_ports()
                      .begin(),
                  metrics_attributes_static_.software_metrics_config()
                      .socket_stat_ports()
                      .end()),
        nf_port_set_(metrics_attributes_static_.software_metrics_config()
                         .netfilter_ports()
                         .begin(),
                     metrics_attributes_static_.software_metrics_config()
                         .netfilter_ports()
                         .end()),
        executor_(std::make_unique<ShellExecutor>()) {}

  SoftwareMetrics(SoftwareMetricsAttributesStatic& software_attributes_static,
                  std::unique_ptr<CommandExecutor> executor)
      : metrics_attributes_static_(software_attributes_static),
        ss_port_set_(metrics_attributes_static_.software_metrics_config()
                      .socket_stat_ports()
                      .begin(),
                  metrics_attributes_static_.software_metrics_config()
                      .socket_stat_ports()
                      .end()),
        nf_port_set_(metrics_attributes_static_.software_metrics_config()
                         .netfilter_ports()
                         .begin(),
                     metrics_attributes_static_.software_metrics_config()
                         .netfilter_ports()
                         .end()),
        executor_(std::move(executor)) {}
  void StoreData(SoftwareMetricsValue* metric_data)
      ABSL_LOCKS_EXCLUDED(metric_data_mutex_);

  absl::StatusOr<NetFilterStates> UpdateNetFilterStats();
  absl::StatusOr<SocketStatStates> UpdateSocketStats();

  const SoftwareMetricsAttributesStatic metrics_attributes_static_;
  const absl::flat_hash_set<int32_t> ss_port_set_;
  const absl::flat_hash_set<int32_t> nf_port_set_;

  mutable absl::Mutex metric_attributes_dynamic_mutex_;
  SoftwareMetricsAttributesDynamic metrics_attributes_dynamic_
      ABSL_GUARDED_BY(metric_attributes_dynamic_mutex_);

  std::unique_ptr<CommandExecutor> executor_;
  mutable absl::Mutex metric_data_mutex_;
  SoftwareMetricsValue values_ ABSL_GUARDED_BY(metric_data_mutex_);
};

}  // namespace milotic_tlbmc

#endif  // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_METRICS_SOFTWARE_METRICS_H_
