/**
 * 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 "unit/TestBase.h"
#include "unit/Catch.h"
#include "c2/ControllerSocketMetricsPublisher.h"
#include "minifi-cpp/core/state/nodes/MetricsBase.h"
#include "core/state/nodes/QueueMetrics.h"
#include "core/state/nodes/ResponseNodeLoader.h"
#include "properties/Configure.h"

namespace org::apache::nifi::minifi::test {

class TestQueueMetrics : public state::response::ResponseNodeImpl {
 public:
  TestQueueMetrics() {
    metrics_ = {
      {"queue_size", 1, {{"connection_name", "con1"}}},
      {"queue_size_max", 2, {{"connection_name", "con1"}}},
      {"queue_size", 3, {{"connection_name", "con2"}}},
      {"queue_size_max", 3, {{"connection_name", "con2"}}},
    };
  }

  std::vector<state::response::SerializedResponseNode> serialize() override {
    return {};
  }

  std::vector<state::PublishedMetric> calculateMetrics() override {
    return metrics_;
  }

 protected:
  std::vector<state::PublishedMetric> metrics_;
};

class TestControllerSocketMetricsPublisher : public c2::ControllerSocketMetricsPublisher {
 public:
  using ControllerSocketMetricsPublisher::ControllerSocketMetricsPublisher;
  void setQueueMetricsNode(std::shared_ptr<state::response::ResponseNode> node) {
    queue_metrics_node_ = std::move(node);
  }

  [[nodiscard]] std::shared_ptr<org::apache::nifi::minifi::state::response::ResponseNode> getQueueMetricsNode() const {
    return queue_metrics_node_;
  }
};

class ControllerSocketMetricsPublisherTestFixture {
 public:
  ControllerSocketMetricsPublisherTestFixture()
      : configuration_(std::make_shared<ConfigureImpl>()),
        response_node_loader_(std::make_shared<state::response::ResponseNodeLoaderImpl>(configuration_, std::vector<std::shared_ptr<core::RepositoryMetricsSource>>{}, nullptr)),
        test_response_node_(std::make_shared<TestQueueMetrics>()),
        controller_socket_metrics_publisher_("test_publisher") {
    controller_socket_metrics_publisher_.initialize(configuration_, response_node_loader_);
  }

 protected:
  std::shared_ptr<Configure> configuration_;
  std::shared_ptr<state::response::ResponseNodeLoader> response_node_loader_;
  std::shared_ptr<TestQueueMetrics> test_response_node_;
  TestControllerSocketMetricsPublisher controller_socket_metrics_publisher_;
};

TEST_CASE_METHOD(ControllerSocketMetricsPublisherTestFixture, "Load and clear", "[ControllerSocketMetricsPublisher]") {
  controller_socket_metrics_publisher_.loadMetricNodes(nullptr);
  auto node = controller_socket_metrics_publisher_.getQueueMetricsNode();
  auto queue_metrics = dynamic_cast<state::response::QueueMetrics*>(node.get());
  REQUIRE(queue_metrics);
  controller_socket_metrics_publisher_.clearMetricNodes();
  REQUIRE(!controller_socket_metrics_publisher_.getQueueMetricsNode());
}

TEST_CASE_METHOD(ControllerSocketMetricsPublisherTestFixture, "Test getting queue sizes", "[ControllerSocketMetricsPublisher]") {
  auto sizes = controller_socket_metrics_publisher_.getQueueSizes();
  REQUIRE(sizes.empty());
  controller_socket_metrics_publisher_.setQueueMetricsNode(test_response_node_);
  sizes = controller_socket_metrics_publisher_.getQueueSizes();
  REQUIRE(sizes.size() == 2);
  CHECK(sizes["con1"].queue_size == 1);
  CHECK(sizes["con1"].queue_size_max == 2);
  CHECK(sizes["con2"].queue_size == 3);
  CHECK(sizes["con2"].queue_size_max == 3);
}

TEST_CASE_METHOD(ControllerSocketMetricsPublisherTestFixture, "Test getting full connections", "[ControllerSocketMetricsPublisher]") {
  auto full_connections = controller_socket_metrics_publisher_.getFullConnections();
  REQUIRE(full_connections.empty());
  controller_socket_metrics_publisher_.setQueueMetricsNode(test_response_node_);
  full_connections = controller_socket_metrics_publisher_.getFullConnections();
  REQUIRE(full_connections.size() == 1);
  REQUIRE(full_connections.contains("con2"));
}

TEST_CASE_METHOD(ControllerSocketMetricsPublisherTestFixture, "Test getting connections", "[ControllerSocketMetricsPublisher]") {
  auto connections = controller_socket_metrics_publisher_.getConnections();
  REQUIRE(connections.empty());
  controller_socket_metrics_publisher_.setQueueMetricsNode(test_response_node_);
  connections = controller_socket_metrics_publisher_.getConnections();
  REQUIRE(connections.size() == 2);
  REQUIRE(connections.contains("con1"));
  REQUIRE(connections.contains("con2"));
}

TEST_CASE_METHOD(ControllerSocketMetricsPublisherTestFixture, "Test getting manifest", "[ControllerSocketMetricsPublisher]") {
  auto agent_manifest = controller_socket_metrics_publisher_.getAgentManifest();
  CHECK(agent_manifest.find("\"agentManifestHash\":") != std::string::npos);
  CHECK(agent_manifest.find("\"agentManifest\":") != std::string::npos);
  CHECK(agent_manifest.find("\"buildInfo\":") != std::string::npos);
  CHECK(agent_manifest.find("\"bundles\": [") != std::string::npos);
  CHECK(agent_manifest.find("\"componentManifest\": {") != std::string::npos);
  CHECK(agent_manifest.find("\"supportedOperations\": [") != std::string::npos);
  CHECK(agent_manifest.find("\"type\": \"describe\"") != std::string::npos);
  CHECK(agent_manifest.find("\"availableProperties\": [") != std::string::npos);
  CHECK(agent_manifest.find("\"agentType\": \"cpp\"") != std::string::npos);
}

TEST_CASE_METHOD(ControllerSocketMetricsPublisherTestFixture, "Test getting flow status", "[ControllerSocketMetricsPublisher]") {
  auto flow_status = controller_socket_metrics_publisher_.getFlowStatus({});
  CHECK(flow_status.find("\"controllerServiceStatusList\":") != std::string::npos);
  CHECK(flow_status.find("\"connectionStatusList\":") != std::string::npos);
  CHECK(flow_status.find("\"remoteProcessGroupStatusList\":") != std::string::npos);
  CHECK(flow_status.find("\"instanceStatus\":") != std::string::npos);
  CHECK(flow_status.find("\"systemDiagnosticsStatus\":") != std::string::npos);
  CHECK(flow_status.find("\"processorStatusList\":") != std::string::npos);
  CHECK(flow_status.find("\"errorsGeneratingReport\":[") != std::string::npos);
}

}  // namespace org::apache::nifi::minifi::test
