#include <gtest/gtest.h>
#include <rclcpp/rclcpp.hpp>
#include "brain/cerebrum_node.hpp"

// NOTE: These tests focus on internal helper behaviors introduced during refactor.
// They avoid driving actual action servers; we only validate state transitions
// and parameter parsing side-effects.

using brain::CerebrumNode;

class CerebrumEnhancedFixture : public ::testing::Test {
protected:
  void SetUp() override {
    if (!rclcpp::ok()) {int argc = 0; char ** argv = nullptr; rclcpp::init(argc, argv);}    
    node_ = std::make_shared<CerebrumNode>();
  }
  void TearDown() override {
    node_.reset();
    if (rclcpp::ok()) {rclcpp::shutdown();}
  }
  std::shared_ptr<CerebrumNode> node_;
};

TEST_F(CerebrumEnhancedFixture, ResolveSkillsFileAllowsEmptyCustom) {
  // Recreate node with explicit empty override param to ensure fallback path chosen.
  rclcpp::NodeOptions opts; opts.append_parameter_override("skills_file", "");
  auto n2 = std::make_shared<CerebrumNode>(opts);
  // Can't directly call ResolveSkillsFile (private), but construction log side-effects
  // are not easily captured; thus we just assert node constructed.
  SUCCEED();
}

TEST_F(CerebrumEnhancedFixture, RandomSkillPickCountClamp) {
  rclcpp::NodeOptions opts; opts.append_parameter_override("random_skill_pick_count", 0);
  auto n2 = std::make_shared<CerebrumNode>(opts);
  // Indirect validation: pick random should return at least 1 or empty if filtering; just ensure no crash.
  auto picked = n2->PickRandomActionSkills(5);
  SUCCEED();
}

TEST_F(CerebrumEnhancedFixture, ParseListStringDeduplicatesOrderPreserved) {
  auto vec = CerebrumNode::ParseListString("x,x,y,z,y");
  ASSERT_EQ(vec.size(), 3u);
  EXPECT_EQ(vec[0], "x");
  EXPECT_EQ(vec[1], "y");
  EXPECT_EQ(vec[2], "z");
}

TEST_F(CerebrumEnhancedFixture, RegisterSkillBtActionsIdempotent) {
  // Call internal registration twice via public sequence selection side-effect.
  // We can't directly enumerate registrations without accessing BT factory internals.
  // So we exercise RunVlmModel twice and ensure no crash / exception.
  node_->RunVlmModel();
  node_->RunVlmModel();
  SUCCEED();
}

TEST_F(CerebrumEnhancedFixture, UpdateBehaviorTreeSetsPendingRun) {
  node_->RunVlmModel();
  // Force an update cycle
  node_->CancelActiveExecuteBtGoal();
  node_->UpdateBehaviorTree();
  // ExecuteBehaviorTree may clear it quickly; just ensure callable without crash.
  rclcpp::executors::SingleThreadedExecutor exec; exec.add_node(node_); exec.spin_some();
  SUCCEED();
}
