#include "tlbmc/metrics/software_metrics.h"

#include <cstdint>
#include <memory>
#include <sstream>
#include <string>

#include "google/protobuf/duration.pb.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/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/synchronization/mutex.h"
#include "g3/macros.h"
#include "nlohmann/json.hpp"
#include "resource.pb.h"
#include "software_metrics.pb.h"
#include "tlbmc/time/time.h"
#include "tlbmc/utils/command_executor.h"
namespace milotic_tlbmc {

SoftwareMetricsAttributesStatic SoftwareMetrics::CreateStaticAttributes(
    const SoftwareMetricsConfig& software_metrics_config) {
  SoftwareMetricsAttributesStatic metric_attributes_static;
  *metric_attributes_static.mutable_software_metrics_config() =
      software_metrics_config;
  return metric_attributes_static;
}

absl::StatusOr<SocketStatStates> SoftwareMetrics::UpdateSocketStats() {
  ECCLESIA_ASSIGN_OR_RETURN(std::string cmd_output,
                            executor_->Execute(*kSocketStatCmd));

  SocketStatStates socket_states;
  *socket_states.mutable_timestamp() = Now();

  std::stringstream ss(cmd_output);
  std::string line;
  while (std::getline(ss, line)) {
    if (line.empty()) {
      continue;
    }

    std::stringstream line_stream(line);
    std::string state_str;
    int port_num;
    SocketStatState* state;
    if (line_stream >> state_str >> port_num) {
      if (ss_port_set_.contains(port_num)) {
        state = &(*socket_states.mutable_states())[port_num];
        if (state_str == "LISTEN") {
          state->set_listen(state->listen() + 1);
        } else if (state_str == "ESTAB") {
          state->set_established(state->established() + 1);
        } else if (state_str == "SYN-SENT") {
          state->set_syn_sent(state->syn_sent() + 1);
        } else if (state_str == "SYN-RECV") {
          state->set_syn_received(state->syn_received() + 1);
        } else if (state_str == "FIN-WAIT-1") {
          state->set_fin_wait_one(state->fin_wait_one() + 1);
        } else if (state_str == "FIN-WAIT-2") {
          state->set_fin_wait_two(state->fin_wait_two() + 1);
        } else if (state_str == "TIME-WAIT") {
          state->set_time_wait(state->time_wait() + 1);
        } else if (state_str == "CLOSE-WAIT") {
          state->set_close_wait(state->close_wait() + 1);
        } else if (state_str == "LAST-ACK") {
          state->set_last_ack(state->last_ack() + 1);
        } else if (state_str == "CLOSING") {
          state->set_closing(state->closing() + 1);
        }
      }
    }
  }
  if (socket_states.states_size() > 0) {
    return socket_states;
  }
  return absl::NotFoundError(
      "No matching NFT rules found for configured ports.");
}

absl::StatusOr<NetFilterStates> SoftwareMetrics::UpdateNetFilterStats() {
  ECCLESIA_ASSIGN_OR_RETURN(absl::string_view cmd_output,
                            executor_->Execute(*kNetFilterCmd));
  NetFilterStates nf_states;
  *nf_states.mutable_timestamp() = Now();
  // Parse JSON output
  nlohmann::json nft_json = nlohmann::json::parse(cmd_output, nullptr, false);
  if (nft_json.is_discarded()) {
    return absl::NotFoundError("Failed to parse JSON output from nft.");
  }
  if (!nft_json.contains("nftables") || !nft_json["nftables"].is_array()) {
    return absl::NotFoundError(
        "nftables array not found in JSON output from nft.");
  }

  // Iterate through the rules and extract data for the ports we need.
  for (const nlohmann::json& item : nft_json["nftables"]) {
    if (!item.contains("rule") || !item["rule"].is_object()) {
      continue;
    }
    const nlohmann::json& rule = item["rule"];
    if (!rule.contains("comment") || !rule["comment"].is_string()) {
      continue;
    }

    // Ensure the comment refers to one of our counter rules
    absl::string_view port_str = rule["comment"].get<absl::string_view>();
    if (!absl::ConsumePrefix(&port_str, "tcp-server-") ||
        !absl::ConsumeSuffix(&port_str, "-synack")) {
      continue;
    }

    // Make sure we have an actual port and we are configured to collect this.
    int32_t port_id;
    if (!absl::SimpleAtoi(port_str, &port_id) ||
        !nf_port_set_.contains(port_id)) {
      continue;
    }

    // This rule is for one of our target ports. Now extract the packet count.
    if (!rule.contains("expr") || !rule["expr"].is_array() ||
        rule["expr"].size() != 1) {
      LOG(WARNING) << "Rule for port " << port_id
                   << " has unexpected expr structure.";

      continue;
    }
    const nlohmann::json& counter_expr = rule["expr"][0];
    if (!counter_expr.contains("counter") ||
        !counter_expr["counter"].is_object() ||
        !counter_expr["counter"].contains("packets") ||
        !counter_expr["counter"]["packets"].is_number()) {
      LOG(WARNING) << "Rule for port " << port_id
                   << " is missing packet counter.";

      continue;
    }

    NetFilterState* state = nf_states.add_states();
    state->set_port(port_id);
    state->set_num_connections(
        counter_expr["counter"]["packets"].get<uint64_t>());
  }

  if (nf_states.states_size() > 0) {
    return nf_states;
  }

  return absl::NotFoundError(
      "No matching NFT rules found for configured ports.");
}

void SoftwareMetrics::StoreData(SoftwareMetricsValue* metric_data) {
  // NOLINTNEXTLINE: Yocto's Abseil is old and only supports pointer type
  absl::MutexLock lock(&metric_data_mutex_);
  values_ = *metric_data;
}

absl::StatusOr<std::unique_ptr<SoftwareMetrics>>
SoftwareMetrics::CreateWithExecutorForUnitTest(
    const SoftwareMetricsConfig& config,
    absl::flat_hash_map<std::string, absl::StatusOr<std::string>>&
        command_map) {
  SoftwareMetricsAttributesStatic software_attributes_static =
      CreateStaticAttributes(config);
  std::unique_ptr<SoftwareMetrics> ptr(
      new SoftwareMetrics(software_attributes_static));

  return ptr;
}

absl::StatusOr<std::unique_ptr<SoftwareMetrics>> SoftwareMetrics::Create(
    const SoftwareMetricsConfig& config) {
  SoftwareMetricsAttributesStatic software_attributes_static =
      CreateStaticAttributes(config);
  std::unique_ptr<SoftwareMetrics> ptr(
      new SoftwareMetrics(software_attributes_static));
  return ptr;
}

void SoftwareMetrics::RefreshOnce(absl::AnyInvocable<void()> callback) {
  SoftwareMetricsValue new_values;
  {
    // NOLINTNEXTLINE: Yocto's Abseil is old and only supports pointer type
    absl::MutexLock lock(&metric_data_mutex_);
    new_values = values_;
  }

  bool update_required = false;
  if (!ss_port_set_.empty()) {
    absl::StatusOr<SocketStatStates> socket_stats = UpdateSocketStats();
    if (socket_stats.ok()) {
      *new_values.mutable_socket_stat_state() = *socket_stats;
      update_required = true;
    } else {
      LOG(ERROR) << "Failed to update socket stats: " << socket_stats.status();
    }
  }
  if (!nf_port_set_.empty()) {
    absl::StatusOr<NetFilterStates> netfilter_stats = UpdateNetFilterStats();
    if (netfilter_stats.ok()) {
      *new_values.mutable_netfilter_state() = *netfilter_stats;
      update_required = true;
    } else {
      LOG(ERROR) << "Failed to update netfilter stats: "
                 << netfilter_stats.status();
    }
  }
  // We start off using the last successful set of values read for software
  // metrics, if the update fails, we will not replace the stored values
  // in memory. If any are successful we need to copy them back in.
  if (update_required) {
    StoreData(&new_values);
  }
  if (callback) {
    callback();
  }
}

}  // namespace milotic_tlbmc
