// Copyright 2026 Google LLC
//
// Licensed 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
//
//    https://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 "tracing/span.h"

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

#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "tracing/noop_tracing.h"
#include "tracing/tracer.h"
#include "tracing/tracer_factory.h"

namespace credentio_tracing {
namespace {

class MockSpan : public Span {
 public:
  MOCK_METHOD(void, SetAttribute, (absl::string_view key, AttributeValue value),
              (override));
  MOCK_METHOD(void, AddEvent, (absl::string_view name), (override));
  MOCK_METHOD(void, SetStatus, (const absl::Status& status), (override));
  MOCK_METHOD(void, End, (), (override));
};

TEST(AttributeValueTest, SupportsExpectedTypes) {
  AttributeValue str_val = std::string("test_string");
  EXPECT_EQ(std::get<std::string>(str_val), "test_string");

  AttributeValue uint_val = uint64_t{42};
  EXPECT_EQ(std::get<uint64_t>(uint_val), 42);

  AttributeValue int_val = int64_t{42};
  EXPECT_EQ(std::get<int64_t>(int_val), 42);

  AttributeValue double_val = 3.14159;
  EXPECT_DOUBLE_EQ(std::get<double>(double_val), 3.14159);

  AttributeValue bool_val = true;
  EXPECT_TRUE(std::get<bool>(bool_val));
}

TEST(SpanTest, MockSpanInvocations) {
  MockSpan span;
  EXPECT_CALL(span, SetAttribute("key", AttributeValue(int64_t{123})));
  EXPECT_CALL(span, AddEvent("event_name"));
  EXPECT_CALL(span, SetStatus(absl::OkStatus()));
  EXPECT_CALL(span, End());

  span.SetAttribute("key", int64_t{123});
  span.AddEvent("event_name");
  span.SetStatus(absl::OkStatus());
  span.End();
}

TEST(SpanTest, EndWithStatusInvocations) {
  MockSpan span;
  absl::Status test_status = absl::InvalidArgumentError("invalid argument");
  EXPECT_CALL(span, SetStatus(test_status));
  EXPECT_CALL(span, End());

  span.EndWithStatus(test_status);
}

TEST(NoopSpanTest, AllMethodsExecuteWithoutError) {
  NoopSpan span;

  span.SetAttribute("key_str", std::string("value"));
  span.SetAttribute("key_int", int64_t{42});
  span.SetAttribute("key_double", 3.14);
  span.SetAttribute("key_bool", true);

  span.AddEvent("test_event");
  span.SetStatus(absl::OkStatus());
  span.SetStatus(absl::InvalidArgumentError("invalid argument"));
  span.End();
}

TEST(NoopTracerTest, StartSpanReturnsNonNullNoopSpan) {
  NoopTracer tracer;
  std::unique_ptr<Span> span = tracer.StartSpan("test_span");
  ASSERT_NE(span, nullptr);

  span->SetAttribute("key", int64_t{100});
  span->AddEvent("event");
  span->SetStatus(absl::OkStatus());
  span->End();
}

TEST(TracerFactoryTest, DefaultGlobalFactoryIsNoopTracerFactory) {
  auto factory = TracerFactory::GetGlobalFactory();
  ASSERT_NE(factory, nullptr);
  auto tracer = factory->GetTracer("test_tracer");
  ASSERT_NE(tracer, nullptr);
  auto span = tracer->StartSpan("test_span");
  ASSERT_NE(span, nullptr);
}

class MockCustomTracerFactory : public TracerFactory {
 public:
  MOCK_METHOD(std::shared_ptr<Tracer>, GetTracer,
              (absl::string_view tracer_name), (const, override));
};

TEST(TracerFactoryTest, GlobalFactoryRegistration) {
  auto initial_factory = TracerFactory::GetGlobalFactory();
  EXPECT_NE(initial_factory, nullptr);

  auto custom_factory = std::make_shared<MockCustomTracerFactory>();
  TracerFactory::RegisterGlobalFactory(custom_factory);

  EXPECT_EQ(TracerFactory::GetGlobalFactory(), custom_factory);

  // Restore original factory state after test
  TracerFactory::RegisterGlobalFactory(initial_factory);
}

TEST(TracerFactoryTest, RegisterNullptrResetsToNoopTracerFactory) {
  auto initial_factory = TracerFactory::GetGlobalFactory();
  EXPECT_NE(initial_factory, nullptr);

  auto custom_factory = std::make_shared<MockCustomTracerFactory>();
  TracerFactory::RegisterGlobalFactory(custom_factory);
  EXPECT_EQ(TracerFactory::GetGlobalFactory(), custom_factory);

  TracerFactory::RegisterGlobalFactory(nullptr);
  auto current_factory = TracerFactory::GetGlobalFactory();
  ASSERT_NE(current_factory, nullptr);
  EXPECT_NE(current_factory, custom_factory);

  // Restore original factory state after test
  TracerFactory::RegisterGlobalFactory(initial_factory);
}

}  // namespace
}  // namespace credentio_tracing
