/*
 *  Copyright 2026 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>
#include <utility>
#include <vector>

#include "api/audio_options.h"
#include "api/create_modular_peer_connection_factory.h"
#include "api/jsep.h"
#include "api/make_ref_counted.h"
#include "api/media_types.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/scoped_refptr.h"
#include "api/set_local_description_observer_interface.h"
#include "media/base/fake_media_engine.h"
#include "pc/peer_connection.h"
#include "pc/peer_connection_proxy.h"
#include "pc/rtp_transceiver.h"
#include "pc/test/enable_fake_media.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/checks.h"
#include "rtc_base/thread.h"
#include "test/create_test_environment.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/run_loop.h"

namespace webrtc {
namespace {

using test::RunLoop;
using ::testing::IsNull;
using ::testing::NotNull;

// Helper observers that quit the run loop.
class QuitOnSuccessCreateObserver
    : public MockCreateSessionDescriptionObserver {
 public:
  explicit QuitOnSuccessCreateObserver(RunLoop& loop) : loop_(loop) {}
  void OnSuccess(SessionDescriptionInterface* desc) override {
    MockCreateSessionDescriptionObserver::OnSuccess(desc);
    loop_.Quit();
  }
  void OnFailure(RTCError error) override {
    MockCreateSessionDescriptionObserver::OnFailure(error);
    loop_.Quit();
  }

 private:
  RunLoop& loop_;
};

class QuitOnSuccessSetObserver : public SetLocalDescriptionObserverInterface {
 public:
  explicit QuitOnSuccessSetObserver(RunLoop& loop) : loop_(loop) {}
  static scoped_refptr<QuitOnSuccessSetObserver> Create(RunLoop& loop) {
    return make_ref_counted<QuitOnSuccessSetObserver>(loop);
  }
  void OnSetLocalDescriptionComplete(RTCError error) override {
    EXPECT_TRUE(error.ok());
    was_called_ = true;
    loop_.Quit();
  }
  bool called() const { return was_called_; }

 private:
  RunLoop& loop_;
  bool was_called_ = false;
};

}  // namespace

class PeerConnectionAudioOptionsTest : public ::testing::Test {
 public:
  PeerConnectionAudioOptionsTest()
      : network_thread_(Thread::CreateWithSocketServer()) {
    network_thread_->Start();

    PeerConnectionFactoryDependencies dependencies;
    dependencies.network_thread = network_thread_.get();
    dependencies.signaling_thread = Thread::Current();

    EnableFakeMedia(dependencies, std::make_unique<FakeMediaEngine>());
    dependencies.env = CreateTestEnvironment();

    pc_factory_ = CreateModularPeerConnectionFactory(std::move(dependencies));
  }

  RTCError CreatePeerConnection(
      const PeerConnectionInterface::RTCConfiguration& configuration) {
    RTC_DCHECK(!pc_);
    auto result = pc_factory_->CreatePeerConnectionOrError(
        configuration, PeerConnectionDependencies(&observer_));
    if (!result.ok()) {
      return result.MoveError();
    }
    pc_ = result.MoveValue();
    observer_.SetPeerConnectionInterface(pc_.get());
    return result.MoveError();
  }

  // Returns a pointer to the internal PeerConnection implementation.
  PeerConnection* pc() {
    RTC_DCHECK(pc_);
    auto* proxy =
        static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
            pc_.get());
    return static_cast<PeerConnection*>(proxy->internal());
  }
  RunLoop loop_;
  std::unique_ptr<Thread> network_thread_;
  scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
  scoped_refptr<PeerConnectionInterface> pc_;
  MockPeerConnectionObserver observer_;
};

TEST_F(PeerConnectionAudioOptionsTest, AudioOptionsAppliedOnCreateChannel) {
  PeerConnectionInterface::RTCConfiguration config;
  // Set specific audio jitter buffer options in the configuration.
  config.audio_jitter_buffer_max_packets = 123;
  config.audio_jitter_buffer_fast_accelerate = true;
  auto result = CreatePeerConnection(config);
  ASSERT_TRUE(result.ok());

  // Add an audio transceiver. Verify that the internal channel() has not been
  // created yet.
  auto transceiver_result = pc()->AddTransceiver(MediaType::AUDIO);
  ASSERT_TRUE(transceiver_result.ok());
  auto transceivers = pc()->GetTransceiversInternal();
  ASSERT_EQ(transceivers.size(), 1u);
  auto* transceiver_impl = transceivers[0]->internal();
  ASSERT_FALSE(transceiver_impl->HasChannel());

  // Create offer and set local description to trigger CreateChannel.
  auto offer_observer = make_ref_counted<QuitOnSuccessCreateObserver>(loop_);
  pc()->CreateOffer(offer_observer.get(),
                    PeerConnectionInterface::RTCOfferAnswerOptions());
  loop_.Run();
  EXPECT_TRUE(offer_observer->called());
  scoped_refptr<QuitOnSuccessSetObserver> sld_observer =
      QuitOnSuccessSetObserver::Create(loop_);
  pc()->SetLocalDescription(offer_observer->MoveDescription(), sld_observer);
  loop_.Run();
  EXPECT_TRUE(sld_observer->called());

  // Verify that now the channel() exists and that the options were applied to
  // the voice engine.
  ASSERT_TRUE(transceiver_impl->HasChannel());

  auto* media_channel = transceiver_impl->media_receive_channel();
  ASSERT_TRUE(media_channel);
  auto* voice_channel =
      static_cast<FakeVoiceMediaReceiveChannel*>(media_channel);
  EXPECT_EQ(voice_channel->options().audio_jitter_buffer_max_packets, 123);
  EXPECT_EQ(voice_channel->options().audio_jitter_buffer_fast_accelerate, true);
}
}  // namespace webrtc
