#ifndef P2P_DTLS_DTLS_ICE_INTEGRATION_FIXTURE_H_
#define P2P_DTLS_DTLS_ICE_INTEGRATION_FIXTURE_H_
/*
 *  Copyright 2025 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 <atomic>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "api/candidate.h"
#include "api/crypto/crypto_options.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "api/field_trials.h"
#include "api/ice_transport_interface.h"
#include "api/make_ref_counted.h"
#include "api/numerics/samples_stats_counter.h"
#include "api/scoped_refptr.h"
#include "api/test/create_network_emulation_manager.h"
#include "api/test/network_emulation_manager.h"
#include "api/test/simulated_network.h"
#include "api/test/time_controller.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "p2p/base/basic_packet_socket_factory.h"
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/p2p_transport_channel.h"
#include "p2p/base/port_allocator.h"
#include "p2p/base/transport_description.h"
#include "p2p/client/basic_port_allocator.h"
#include "p2p/dtls/dtls_transport.h"
#include "p2p/test/fake_ice_lite_agent.h"
#include "p2p/test/fake_ice_transport.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/checks.h"
#include "rtc_base/fake_network.h"
#include "rtc_base/logging.h"
#include "rtc_base/network.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/ssl_fingerprint.h"
#include "rtc_base/ssl_identity.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/thread.h"
#include "rtc_base/virtual_socket_server.h"
#include "test/create_test_field_trials.h"
#include "test/time_controller/simulated_time_controller.h"
#include "test/wait_until.h"

namespace webrtc {
namespace dtls_ice_integration_fixture {

constexpr int kDefaultTimeout = 30000;

struct EndpointConfig {
  SSLProtocolVersion max_protocol_version;
  IceRole ice_role;
  SSLRole ssl_role;
  bool ice_lite = false;
  bool dtls_in_stun = false;
  bool pqc = false;

  template <typename Sink>
  friend void AbslStringify(Sink& sink, const EndpointConfig& config) {
    sink.Append("[ dtls: ");
    sink.Append(config.ssl_role == SSL_SERVER ? "server/" : "client/");
    switch (config.max_protocol_version) {
      case SSL_PROTOCOL_DTLS_10:
        sink.Append("1.0");
        break;
      case SSL_PROTOCOL_DTLS_12:
        sink.Append("1.2");
        break;
      case SSL_PROTOCOL_DTLS_13:
        sink.Append("1.3");
        break;
      default:
        sink.Append("<unknown>");
        break;
    }
    if (config.ice_role == ICEROLE_CONTROLLED) {
      if (config.ice_lite) {
        sink.Append(" ice: lite");
      } else {
        sink.Append(" ice: controlled");
      }
    }
    absl::Format(&sink, " pqc: %u dtls_in_stun: %u ", config.pqc,
                 config.dtls_in_stun);
    sink.Append(" ]");
  }
};

struct TestConfig {
  int pct_loss = -1;
  int client_interface_count = -1;
  int server_interface_count = -1;

  bool ice_lite = false;
  bool client_ssl_client = true;
  SSLProtocolVersion protocol_version;

  // Configuration for the endpoint acting as the ICE controllering.
  EndpointConfig client_config;
  // Configuration for the endpoint acting as the ICE controlled.
  EndpointConfig server_config;

  TestConfig& fix() {
    client_config.ice_role = ICEROLE_CONTROLLING;
    server_config.ice_role = ICEROLE_CONTROLLED;
    client_config.ice_lite = ice_lite;
    server_config.ice_lite = ice_lite;
    if (client_ssl_client) {
      client_config.ssl_role = SSL_CLIENT;
      server_config.ssl_role = SSL_SERVER;
    } else {
      client_config.ssl_role = SSL_SERVER;
      server_config.ssl_role = SSL_CLIENT;
    }
    client_config.max_protocol_version = protocol_version;
    server_config.max_protocol_version = protocol_version;
    return *this;
  }

  template <typename Sink>
  friend void AbslStringify(Sink& sink, const TestConfig& config) {
    if (config.pct_loss >= 0) {
      absl::Format(&sink, "loss: %u ", config.pct_loss);
    }
    if (config.client_interface_count > 1) {
      absl::Format(&sink, "client_interface_count: %u ",
                   config.client_interface_count);
    }
    if (config.server_interface_count > 1) {
      absl::Format(&sink, "server_interface_count: %u ",
                   config.server_interface_count);
    }
    sink.Append("[ client: ");
    AbslStringify(sink, config.client_config);
    sink.Append("[ server: ");
    AbslStringify(sink, config.server_config);
    sink.Append("]");
  }

  static constexpr EndpointConfig kEndpointVariants[] = {
      {
          .dtls_in_stun = false,
          .pqc = false,
      },
      {
          .dtls_in_stun = true,
          .pqc = false,
      },
      {
          .dtls_in_stun = false,
          .pqc = true,
      },
      {
          .dtls_in_stun = true,
          .pqc = true,
      },
  };

  static std::vector<TestConfig> AllVariants() {
    std::vector<TestConfig> out;
    for (auto cc : kEndpointVariants) {
      for (auto sc : kEndpointVariants) {
        if (cc.dtls_in_stun != sc.dtls_in_stun) {
          continue;
        }
        for (auto use_ice_lite : {false, true}) {
          for (auto cic : {true, false}) {
            for (auto p : {SSL_PROTOCOL_DTLS_12, SSL_PROTOCOL_DTLS_13}) {
              auto config = TestConfig{.ice_lite = use_ice_lite,
                                       .client_ssl_client = cic,
                                       .protocol_version = p,
                                       .client_config = cc,
                                       .server_config = sc}
                                .fix();
              if (p == SSL_PROTOCOL_DTLS_12 && (cc.pqc || sc.pqc)) {
                continue;
              }
              out.push_back(config);
            }
          }
        }
      }
    }
    return out;
  }
};

class Base {
 public:
  explicit Base(const TestConfig& config)
      : config_(config),
        ss_(std::make_unique<VirtualSocketServer>()),
        socket_factory_(std::make_unique<BasicPacketSocketFactory>(ss_.get())),
        client_(/* client= */ true, config.client_config),
        server_(/* client= */ false, config.server_config),
        client_ice_parameters_("c_ufrag",
                               "c_icepwd_something_something",
                               false),
        server_ice_parameters_("s_ufrag",
                               "s_icepwd_something_something",
                               false) {}
  virtual ~Base() { TearDown(); }

  struct Endpoint {
    explicit Endpoint(bool client_, const EndpointConfig& config_)
        : client(client_),
          config(config_),
          env(CreateEnvironment(CreateTestFieldTrialsPtr(
              config.dtls_in_stun ? "WebRTC-IceHandshakeDtls/Enabled/" : ""))) {
    }

    bool client;
    EmulatedNetworkManagerInterface* emulated_network_manager = nullptr;
    std::unique_ptr<NetworkManager> network_manager;
    std::unique_ptr<BasicPacketSocketFactory> packet_socket_factory;
    std::unique_ptr<PortAllocator> allocator;
    scoped_refptr<IceTransportInterface> ice_transport;
    std::unique_ptr<DtlsTransportInternalImpl> dtls;

    // Convenience getter for the internal transport.
    IceTransportInternal* ice() { return ice_transport->internal(); }

    // SetRemoteFingerprintFromCert does not actually set the fingerprint,
    // but only store it for setting later.
    bool store_but_dont_set_remote_fingerprint = false;
    std::unique_ptr<SSLFingerprint> remote_fingerprint;

    scoped_refptr<RTCCertificate> local_certificate;
    scoped_refptr<RTCCertificate> remote_certificate;

    EndpointConfig config;
    Environment env;

    void Restart(Base& test) {
      dtls.reset();
      ice_transport = nullptr;
      allocator.reset();
      packet_socket_factory.reset();

      packet_socket_factory = std::make_unique<BasicPacketSocketFactory>(
          emulated_network_manager->socket_factory());
      allocator = std::make_unique<BasicPortAllocator>(
          env, network_manager.get(), packet_socket_factory.get());
      test.SetupIceAndDtls(*this);
      allocator->Initialize();
    }
  };

  // Run benchmark for this TestConfig& `iter` iterations,
  // return statistics.
  SamplesStatsCounter RunBenchmark(int iter) {
    ConfigureEmulatedNetwork(config_.pct_loss, config_.client_interface_count,
                             config_.server_interface_count);
    Prepare();

    SamplesStatsCounter stats(iter);
    for (int i = 0; i < iter; i++) {
      int client_sent = 0;
      std::atomic<int> client_recv = 0;
      int server_sent = 0;
      std::atomic<int> server_recv = 0;
      void* id = this;

      client_thread()->BlockingCall([&]() {
        return client_.dtls->RegisterReceivedPacketCallback(
            id, [&](auto, auto) { client_recv++; });
      });
      server_thread()->BlockingCall([&]() {
        return server_.dtls->RegisterReceivedPacketCallback(
            id, [&](auto, auto) { server_recv++; });
      });

      client_thread()->PostTask(
          [&]() { client_.ice()->MaybeStartGathering(); });
      server_thread()->PostTask(
          [&]() { server_.ice()->MaybeStartGathering(); });

      auto start = CurrentTime();

      while (client_recv == 0 || server_recv == 0) {
        int delay = 50;
        AdvanceTime(TimeDelta::Millis(delay));

        // Send data
        {
          int flags = 0;
          AsyncSocketPacketOptions options;
          std::string a_string(50, 'a');

          if (client_.dtls->writable()) {
            client_thread()->BlockingCall([&]() {
              if (client_.dtls->SendPacket(a_string.c_str(), a_string.length(),
                                           options, flags) > 0) {
                client_sent++;
              }
            });
          }
          if (server_.dtls->writable()) {
            server_thread()->BlockingCall([&]() {
              if (server_.dtls->SendPacket(a_string.c_str(), a_string.length(),
                                           options, flags) > 0) {
                server_sent++;
              }
            });
          }
        }
      }
      auto end = CurrentTime();
      stats.AddSample(SamplesStatsCounter::StatsSample{
          .value = static_cast<double>((end - start).ms()),
          .time = end,
      });
      client_thread()->BlockingCall(
          [&]() { return client_.dtls->DeregisterReceivedPacketCallback(id); });
      server_thread()->BlockingCall(
          [&]() { return server_.dtls->DeregisterReceivedPacketCallback(id); });
      if (i + 1 < iter) {
        client_thread()->BlockingCall([&]() { client_.Restart(*this); });
        server_thread()->BlockingCall([&]() { server_.Restart(*this); });
      }
    }
    return stats;
  }

  static bool IsBoringSsl() { return SSLStreamAdapter::IsBoringSsl(); }

 protected:
  void SetUp() {}

  void TearDown() {
    if (client_thread() != nullptr) {
      client_thread()->BlockingCall([&]() {
        client_.dtls.reset();
        client_.ice_transport = nullptr;
        client_.allocator.reset();
      });
    }

    if (server_thread() != nullptr) {
      server_thread()->BlockingCall([&]() {
        server_.dtls.reset();
        server_.ice_transport = nullptr;
        server_.allocator.reset();
      });
    }
  }

  void ConfigureEmulatedNetwork(int pct_loss = 25,
                                int client_interface_count = 1,
                                int server_interface_count = 1) {
    network_emulation_manager_ =
        CreateNetworkEmulationManager({.time_mode = TimeMode::kSimulated});

    BuiltInNetworkBehaviorConfig networkBehavior;
    networkBehavior.link_capacity = DataRate::KilobitsPerSec(220);
    networkBehavior
        .queue_delay_ms = /* this is one way delay, i.e. divide the rtt by 2 */
        DtlsTransportInternalImpl::kDefaultHandshakeEstimateRttMs / 2;
    networkBehavior.queue_length_packets = 30;
    networkBehavior.loss_percent = pct_loss;

    auto pair = network_emulation_manager_->CreateEndpointPairWithTwoWayRoutes(
        networkBehavior, client_interface_count, server_interface_count);
    client_.emulated_network_manager = pair.first;
    server_.emulated_network_manager = pair.second;
  }

  void Prepare() {
    auto client_certificate =
        RTCCertificate::Create(SSLIdentity::Create("test", KT_DEFAULT));
    auto server_certificate =
        RTCCertificate::Create(SSLIdentity::Create("test", KT_DEFAULT));

    if (network_emulation_manager_ == nullptr) {
      global_time_controller_ = std::make_unique<GlobalSimulatedTimeController>(
          Timestamp::Seconds(10000), ss_.get());
      time_controller_ = global_time_controller_.get();
    } else {
      time_controller_ = network_emulation_manager_->time_controller();
    }

    client_thread()->BlockingCall([&]() {
      SetupEndpoint(client_, client_certificate, server_certificate);
    });

    server_thread()->BlockingCall([&]() {
      SetupEndpoint(server_, client_certificate, server_certificate);
    });

    // Setup the network.
    if (network_emulation_manager_ == nullptr) {
      network_manager_->AddInterface(SocketAddress("192.168.1.1", 0));
    }

    client_thread()->BlockingCall([&]() { client_.allocator->Initialize(); });
    server_thread()->BlockingCall([&]() { server_.allocator->Initialize(); });
  }

  Timestamp CurrentTime() {
    return time_controller_->GetClock()->CurrentTime();
  }

  void AdvanceTime(TimeDelta delta) { time_controller_->AdvanceTime(delta); }

  WaitUntilSettings wait_until_settings(int timeout_ms = kDefaultTimeout) {
    return {
        .timeout = TimeDelta::Millis(timeout_ms),
        .clock = time_controller_,
    };
  }

  Thread* thread(Endpoint& ep) {
    if (ep.emulated_network_manager == nullptr) {
      if (time_controller_ == nullptr) {
        return nullptr;
      }
      return time_controller_->GetMainThread();
    } else {
      return ep.emulated_network_manager->network_thread();
    }
  }

  Thread* client_thread() { return thread(client_); }
  Thread* server_thread() { return thread(server_); }

  Endpoint& dtls_client() {
    return client_.config.ssl_role == SSL_CLIENT ? client_ : server_;
  }
  Endpoint& dtls_server() {
    return client_.config.ssl_role == SSL_SERVER ? client_ : server_;
  }

  void SetRemoteFingerprintFromCert(Endpoint& ep,
                                    const scoped_refptr<RTCCertificate>& cert) {
    ep.remote_fingerprint = SSLFingerprint::CreateFromCertificate(*cert);
    if (ep.store_but_dont_set_remote_fingerprint) {
      return;
    }
    SetRemoteFingerprint(ep);
  }

  void SetRemoteFingerprint(Endpoint& ep) {
    RTC_CHECK(ep.remote_fingerprint);
    RTC_LOG(LS_INFO) << ((&ep == &client_) ? "client" : "server")
                     << "::SetRemoteFingerprint";
    ep.dtls->SetRemoteParameters(
        ep.remote_fingerprint->algorithm,
        reinterpret_cast<const uint8_t*>(ep.remote_fingerprint->digest.data()),
        ep.remote_fingerprint->digest.size(), std::nullopt);
  }

  void SetLocalCertificate(Endpoint& ep,
                           const scoped_refptr<RTCCertificate> certificate) {
    RTC_CHECK(certificate);
    RTC_LOG(LS_INFO) << ((&ep == &client_) ? "client" : "server")
                     << "::SetLocalCertificate: ";
    ep.dtls->SetLocalCertificate(certificate);
  }

  TestConfig config_;
  std::unique_ptr<VirtualSocketServer> ss_;
  std::unique_ptr<BasicPacketSocketFactory> socket_factory_;
  std::unique_ptr<NetworkEmulationManager> network_emulation_manager_;
  std::unique_ptr<GlobalSimulatedTimeController> global_time_controller_;
  TimeController* time_controller_ = nullptr;
  std::unique_ptr<FakeNetworkManager> network_manager_;

  Endpoint client_;
  Endpoint server_;

  IceParameters client_ice_parameters_;
  IceParameters server_ice_parameters_;
  // Used for simlating an ICE Lite agent.
  FakeIceLiteAgentIceControllerFactory
      fake_ice_lite_agent_ice_controller_factory_;

 private:
  void CandidateC2S(IceTransportInternal*, const Candidate& c) {
    server_thread()->PostTask(
        [this, c = c]() { server_.ice()->AddRemoteCandidate(c); });
  }
  void CandidateS2C(IceTransportInternal*, const Candidate& c) {
    client_thread()->PostTask(
        [this, c = c]() { client_.ice()->AddRemoteCandidate(c); });
  }

  void SetupEndpoint(Endpoint& ep,
                     const scoped_refptr<RTCCertificate> client_certificate,
                     const scoped_refptr<RTCCertificate> server_certificate) {
    thread(ep)->BlockingCall([&]() {
      if (!network_manager_) {
        network_manager_ =
            std::make_unique<FakeNetworkManager>(Thread::Current());
      }
      if (network_emulation_manager_ == nullptr) {
        ep.allocator = std::make_unique<BasicPortAllocator>(
            ep.env, network_manager_.get(), socket_factory_.get());
      } else {
        ep.network_manager =
            ep.emulated_network_manager->ReleaseNetworkManager();
        ep.packet_socket_factory = std::make_unique<BasicPacketSocketFactory>(
            ep.emulated_network_manager->socket_factory());
        ep.allocator = std::make_unique<BasicPortAllocator>(
            ep.env, ep.network_manager.get(), ep.packet_socket_factory.get());
      }
      ep.local_certificate =
          ep.client ? client_certificate : server_certificate;
      ep.remote_certificate =
          ep.client ? server_certificate : client_certificate;
      SetupIceAndDtls(ep);
    });
  }

  void SetupIceAndDtls(Endpoint& ep) {
    // Should we be using the FakeIceLiteAgent?
    bool ice_lite_agent =
        ep.config.ice_lite && ep.config.ice_role == ICEROLE_CONTROLLED;
    ep.allocator->set_flags(ep.allocator->flags() | PORTALLOCATOR_DISABLE_TCP);
    IceTransportInit init(ep.env);
    init.set_port_allocator(ep.allocator.get());
    if (ice_lite_agent) {
      init.set_active_ice_controller_factory(
          &fake_ice_lite_agent_ice_controller_factory_);
    }
    auto channel = P2PTransportChannel::Create(
        ep.client ? "client_transport" : "server_transport",
        /* component= */ 0, std::move(init));
    ep.ice_transport = make_ref_counted<FakeIceTransport>(std::move(channel));

    // Enable(or disable) the dtls_in_stun parameter before
    // DTLS is negotiated.
    IceConfig config;
    config.continual_gathering_policy = GATHER_CONTINUALLY;
    config.dtls_handshake_in_stun = ep.config.dtls_in_stun;
    ep.ice()->SetIceConfig(config);

    // Is peer using ice-lite.
    if (ep.config.ice_lite && ep.config.ice_role == ICEROLE_CONTROLLING) {
      ep.ice()->SetRemoteIceMode(ICEMODE_LITE);
    }

    CryptoOptions crypto_options;
    if (ep.config.pqc) {
      FieldTrials field_trials =
          CreateTestFieldTrials("WebRTC-EnableDtlsPqc/Enabled/");
      crypto_options.ephemeral_key_exchange_cipher_groups.Update(&field_trials);
    }
    ep.dtls = std::make_unique<DtlsTransportInternalImpl>(
        ep.env, ep.ice_transport, crypto_options,
        ep.config.max_protocol_version);

    if (ice_lite_agent) {
      ep.dtls->SetFakeIceLite();
    }

    // Setup ICE.
    ep.ice()->SetIceParameters(ep.client ? client_ice_parameters_
                                         : server_ice_parameters_);
    ep.ice()->SetRemoteIceParameters(ep.client ? server_ice_parameters_
                                               : client_ice_parameters_);
    ep.ice()->SetIceRole(ep.config.ice_role);
    if (ep.client) {
      ep.ice()->SubscribeCandidateGathered(
          this,
          [this](IceTransportInternal* transport, const Candidate& candidate) {
            CandidateC2S(transport, candidate);
          });
    } else {
      ep.ice()->SubscribeCandidateGathered(
          this,
          [this](IceTransportInternal* transport, const Candidate& candidate) {
            CandidateS2C(transport, candidate);
          });
    }

    // Setup DTLS.
    ep.dtls->SetDtlsRole(ep.config.ssl_role);
    SetLocalCertificate(ep, ep.local_certificate);
    SetRemoteFingerprintFromCert(ep, ep.remote_certificate);
  }
};

}  // namespace dtls_ice_integration_fixture
}  // namespace webrtc

#endif  // P2P_DTLS_DTLS_ICE_INTEGRATION_FIXTURE_H_
