// Copyright 2026 The BoringSSL Authors
//
// 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.

use std::{
    collections::VecDeque,
    mem::MaybeUninit,
    pin::pin,
    sync::{
        Arc,
        Mutex, //
    },
    task::Context, //
};

use crate::{
    ReceiveBuffer,
    connection::{
        Client,
        Server,
        TlsConnection, //
    },
    context::TlsContextBuilder,
    credentials::{Certificate, TlsCredential, TlsCredentialBuilder},
    errors::Error,
    io::{
        AbstractReader,
        AbstractSocket,
        AbstractSocketResult,
        AbstractWriter,
        IoStatus, //
    }, //
};

use bssl_x509::{
    certificates::X509Certificate,
    keys::PrivateKey,
    params::Trust,
    store::{
        X509Store,
        X509StoreBuilder, //
    },
};
use futures::future::join;

mod alpn;
mod credentials;
mod datagram;
mod handshake;
mod transport;

pub(crate) const CA: &[u8] = include_bytes!("../../test-data/BoringSSLCATest.crt");
pub(crate) const RSA_SERVER_CERT: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-RSA.crt");
pub(crate) const RSA_SERVER_CERT_DER: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-RSA-Cert.der");
pub(crate) const RSA_SERVER_KEY: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-RSA.key");
pub(crate) const P256_SERVER_CERT: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-ECDSA-P256.crt");
pub(crate) const P256_SERVER_CERT_DER: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-ECDSA-P256-Cert.der");
pub(crate) const P256_SERVER_KEY: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-ECDSA-P256.key");
pub(crate) const P256_SERVER_KEY_DER: &[u8] =
    include_bytes!("../../test-data/BoringSSLServerTest-ECDSA-P256.der");

// DER-encoded DistinguishedName representing "CN=TestCA".
// Can be verified using:
// echo -n "3011310f300d06035504031306546573744341" | xxd -r -p | openssl asn1parse -inform DER
//
// Output:
//   0:d=0  hl=2 l=  17 cons: SEQUENCE
//   2:d=1  hl=2 l=  15 cons: SET
//   4:d=2  hl=2 l=  13 cons: SEQUENCE
//   6:d=3  hl=2 l=   3 prim: OBJECT            :commonName
//  11:d=3  hl=2 l=   6 prim: PRINTABLESTRING   :TestCA
pub(crate) const TEST_CA_DN: &[u8] = b"\x30\x11\x31\x0f\x30\x0d\x06\x03\x55\x04\x03\x13\x06TestCA";

/// Dumb server-client pair that does no certificate verification.
fn dumb_server_client() -> Result<(TlsConnection<Server>, TlsConnection<Client>), Error> {
    let mut server_ctx_builder = TlsContextBuilder::new_tls();
    server_ctx_builder.with_credential(load_x509_credential())?;
    let server_ctx = server_ctx_builder.build();
    let server_conn = server_ctx.new_server_connection().build();

    let mut client_ctx_builder = TlsContextBuilder::new_tls();
    let cert_store = load_trust_store(Trust::SslServer);
    client_ctx_builder.with_certificate_store(&cert_store);
    let client_ctx = client_ctx_builder.build();
    let client_conn = client_ctx.new_client_connection().build();

    Ok((server_conn, client_conn))
}

fn sync_ping_pong<
    M: crate::connection::methods::HasTlsConnectionMethod
        + crate::context::SupportedMode
        + crate::context::HasBasicIo
        + 'static,
>(
    mut server_conn: TlsConnection<Server, M>,
    mut client_conn: TlsConnection<Client, M>,
) -> Result<(), Error> {
    let thread = std::thread::spawn(move || {
        server_conn.accept()?;
        assert!(!server_conn.is_in_handshake());
        // TODO: switch to `From` impls when Rust compiler is bumped to 1.95.0.
        let mut message = [MaybeUninit::uninit(); 21];
        let mut message = ReceiveBuffer::new_uninit(&mut message);
        assert!(matches!(
            server_conn.sync_read(&mut message)?,
            IoStatus::Ok(21)
        ));
        assert_eq!(*message, *b"BoringSSL is awesome!");
        server_conn.sync_write(b"Oh yeah definitely!")?;
        server_conn.established().unwrap().sync_shutdown()?;
        // Second shutdown poll.
        server_conn.established().unwrap().sync_shutdown()?;
        Ok::<_, Error>(())
    });

    client_conn.connect()?;
    assert!(!client_conn.is_in_handshake());
    client_conn.sync_write(b"BoringSSL is awesome!")?;
    let mut message = [MaybeUninit::uninit(); 19];
    let mut message = ReceiveBuffer::new_uninit(&mut message);
    assert!(matches!(
        client_conn.sync_read(&mut message)?,
        IoStatus::Ok(19)
    ));
    assert_eq!(*message, *b"Oh yeah definitely!");
    client_conn.established().unwrap().sync_shutdown()?;
    thread.join().unwrap()?;

    Ok(())
}

pub const TEST_DATA: &[u8] = b"BoringSSL is awesome!";

/// A mocked pipe that will never close or emit EOF.
#[derive(Default)]
pub struct MockPipe {
    pub buf: VecDeque<u8>,
    pub data_waker: Option<std::task::Waker>,
}

pub struct OperationState {
    /// Whether the mock I/O object needs to return Pending for testing purpose.
    pub need_yield: bool,
    /// A parked waker.
    pub yield_waker: Option<std::task::Waker>,
}

impl Default for OperationState {
    fn default() -> Self {
        Self {
            need_yield: true,
            yield_waker: None,
        }
    }
}

pub struct MockSocket<P> {
    pub read_pipe: Arc<Mutex<P>>,
    pub write_pipe: Arc<Mutex<P>>,
    pub read_state: Arc<Mutex<OperationState>>,
    pub write_state: Arc<Mutex<OperationState>>,
}

impl AbstractReader for MockSocket<MockPipe> {
    fn read(&mut self, cx: Option<&mut Context<'_>>, buf: &mut [u8]) -> AbstractSocketResult {
        let mut state = self.read_state.lock().unwrap();
        if state.need_yield {
            if let Some(waker) = cx.as_ref().map(|c| c.waker().clone()) {
                state.yield_waker = Some(waker);
                return AbstractSocketResult::Retry;
            }
        }

        let mut pipe = self.read_pipe.lock().unwrap();
        let mut read = 0;
        if buf.is_empty() {
            return AbstractSocketResult::Ok(0);
        }
        while read < buf.len() {
            let Some(b) = pipe.buf.pop_front() else {
                break;
            };
            buf[read] = b;
            read += 1;
        }

        if read == 0 {
            if let Some(waker) = cx.as_ref().map(|c| c.waker().clone()) {
                pipe.data_waker = Some(waker);
            }
            // TODO(@xfding): this is correct for async sockets, but sync sockets should block until
            // arrival of new data.
            // We will need a condvar for this behaviour.
            return AbstractSocketResult::Retry;
        }
        // Reset for next operation
        state.need_yield = true;
        AbstractSocketResult::Ok(read)
    }
}

impl AbstractWriter for MockSocket<MockPipe> {
    fn write(&mut self, cx: Option<&mut Context<'_>>, buf: &[u8]) -> AbstractSocketResult {
        let mut state = self.write_state.lock().unwrap();
        if state.need_yield {
            if let Some(waker) = cx.as_ref().map(|c| c.waker().clone()) {
                state.yield_waker = Some(waker);
                return AbstractSocketResult::Retry;
            }
        }

        let mut pipe = self.write_pipe.lock().unwrap();
        pipe.buf.extend(buf.iter().copied());

        // Wake reader if they are waiting for data
        if let Some(waker) = pipe.data_waker.take() {
            waker.wake();
        }

        // Reset for next operation
        state.need_yield = true;

        AbstractSocketResult::Ok(buf.len())
    }

    fn flush(&mut self, _: Option<&mut Context<'_>>) -> AbstractSocketResult {
        AbstractSocketResult::Ok(0)
    }
}

impl AbstractSocket for MockSocket<MockPipe> {}

pub struct MockExecutor {
    pub states: Vec<Arc<Mutex<OperationState>>>,
}

impl MockExecutor {
    pub fn run<F: std::future::Future>(&mut self, f: F) -> F::Output {
        let waker = futures::task::noop_waker();
        let mut cx = Context::from_waker(&waker);
        let mut f = pin!(f);

        loop {
            match f.as_mut().poll(&mut cx) {
                std::task::Poll::Ready(res) => return res,
                std::task::Poll::Pending => {
                    // Resolve forced yields and reset flags
                    for state in &self.states {
                        let mut state = state.lock().unwrap();
                        if let Some(waker) = state.yield_waker.take() {
                            state.need_yield = false;
                            waker.wake();
                        }
                    }
                }
            }
        }
    }
}

pub fn create_mock_socket<P: Default>() -> (MockSocket<P>, MockSocket<P>, MockExecutor) {
    let pipe1 = Arc::new(Mutex::new(P::default()));
    let pipe2 = Arc::new(Mutex::new(P::default()));

    let socket1 = MockSocket {
        read_pipe: pipe1.clone(),
        write_pipe: pipe2.clone(),
        read_state: Arc::new(Mutex::new(OperationState::default())),
        write_state: Arc::new(Mutex::new(OperationState::default())),
    };

    let socket2 = MockSocket {
        read_pipe: pipe2,
        write_pipe: pipe1,
        read_state: Arc::new(Mutex::new(OperationState::default())),
        write_state: Arc::new(Mutex::new(OperationState::default())),
    };

    let executor = MockExecutor {
        states: vec![
            socket1.read_state.clone(),
            socket1.write_state.clone(),
            socket2.read_state.clone(),
            socket2.write_state.clone(),
        ],
    };

    (socket1, socket2, executor)
}

pub fn create_mock_pipe() -> (MockSocket<MockPipe>, MockSocket<MockPipe>, MockExecutor) {
    create_mock_socket::<MockPipe>()
}

/// A mock datagram transport that never shuts down.
#[derive(Default)]
pub struct MockDatagram {
    pub buf: VecDeque<Vec<u8>>,
    pub data_waker: Option<std::task::Waker>,
}

impl AbstractReader for MockSocket<MockDatagram> {
    fn read(&mut self, cx: Option<&mut Context<'_>>, buf: &mut [u8]) -> AbstractSocketResult {
        let mut state = self.read_state.lock().unwrap();
        if state.need_yield {
            if let Some(waker) = cx.as_ref().map(|c| c.waker().clone()) {
                state.yield_waker = Some(waker);
                return AbstractSocketResult::Retry;
            }
        }

        let mut pipe = self.read_pipe.lock().unwrap();
        let Some(packet) = pipe.buf.pop_front() else {
            if let Some(waker) = cx.as_ref().map(|c| c.waker().clone()) {
                pipe.data_waker = Some(waker);
            }
            return AbstractSocketResult::Retry;
        };

        let len = packet.len().min(buf.len());
        buf[..len].copy_from_slice(&packet[..len]);

        state.need_yield = true;

        AbstractSocketResult::Ok(len)
    }
}

impl AbstractWriter for MockSocket<MockDatagram> {
    fn write(&mut self, cx: Option<&mut Context<'_>>, buf: &[u8]) -> AbstractSocketResult {
        let mut state = self.write_state.lock().unwrap();
        if state.need_yield {
            if let Some(waker) = cx.as_ref().map(|c| c.waker().clone()) {
                state.yield_waker = Some(waker);
                return AbstractSocketResult::Retry;
            }
        }

        let mut pipe = self.write_pipe.lock().unwrap();
        pipe.buf.push_back(buf.to_vec());

        if let Some(waker) = pipe.data_waker.take() {
            waker.wake();
        }

        state.need_yield = true;

        AbstractSocketResult::Ok(buf.len())
    }

    fn flush(&mut self, _: Option<&mut Context<'_>>) -> AbstractSocketResult {
        AbstractSocketResult::Ok(0)
    }
}

impl AbstractSocket for MockSocket<MockDatagram> {}

pub(crate) fn create_mock_datagram() -> (
    MockSocket<MockDatagram>,
    MockSocket<MockDatagram>,
    MockExecutor,
) {
    create_mock_socket::<MockDatagram>()
}

/// Builds a [`TlsCredential`] from the test RSA certificate chain (server cert + CA)
/// and private key.
pub(crate) fn load_x509_credential() -> TlsCredential {
    let ca = Certificate::parse_one_from_pem(CA, None).unwrap();
    let server_cert = Certificate::parse_one_from_pem(RSA_SERVER_CERT, None).unwrap();
    let server_key = PrivateKey::from_pem(RSA_SERVER_KEY, || unreachable!()).unwrap();

    let mut builder = TlsCredentialBuilder::new();
    builder
        .with_certificate_chain(&[server_cert, ca])
        .unwrap()
        .with_private_key(server_key)
        .unwrap();
    builder.build().unwrap()
}

/// Builds an X509 trust store with the test CA certificate.
pub(crate) fn load_trust_store(trust: Trust) -> X509Store {
    let mut cert_store = X509StoreBuilder::new();
    cert_store
        .set_trust(trust)
        .unwrap()
        .add_cert(X509Certificate::parse_one_from_pem(CA).unwrap())
        .unwrap();
    cert_store.build()
}

/// Runs an async TLS handshake between a client and server connection using mock
/// pipe IO. Returns `Ok(())` on successful handshake.
pub(crate) fn run_async_handshake(
    mut client_conn: TlsConnection<Client>,
    mut server_conn: TlsConnection<Server>,
) -> Result<(), Error> {
    let (client_socket, server_socket, mut executor) = create_mock_pipe();
    client_conn.set_io(client_socket)?;
    server_conn.set_io(server_socket)?;

    executor.run(async {
        let client_handshake = async {
            assert!(client_conn.async_handshake().await?.is_none());
            Ok::<(), Error>(())
        };
        let server_handshake = async {
            assert!(server_conn.async_handshake().await?.is_none());
            Ok::<(), Error>(())
        };
        futures::future::try_join(client_handshake, server_handshake).await?;
        Ok::<(), Error>(())
    })
}

#[test]
fn test_async() -> Result<(), Error> {
    let (mut server_conn, mut client_conn) = dumb_server_client()?;

    let (client_socket, server_socket, mut executor) = create_mock_pipe();

    server_conn.set_io(server_socket)?;
    client_conn.set_io(client_socket)?;

    let test_future = async move {
        let server_handshake = drive_handshake(&mut server_conn);
        let client_handshake = drive_handshake(&mut client_conn);
        join(server_handshake, client_handshake).await;

        let server_data = async move {
            let mut buf = [0u8; TEST_DATA.len()];
            let mut read_bytes = 0;
            while read_bytes < TEST_DATA.len() {
                match server_conn
                    .as_pin_mut()
                    .async_read(&mut buf[read_bytes..])
                    .await
                    .unwrap()
                {
                    IoStatus::Ok(n) => read_bytes += n,
                    IoStatus::EndOfStream => break,
                    _ => {}
                }
            }
            assert_eq!(&buf, TEST_DATA);
        };

        let client_data = async move {
            let _ = client_conn
                .as_pin_mut()
                .async_write(TEST_DATA)
                .await
                .unwrap();
        };

        join(server_data, client_data).await;
    };

    executor.run(test_future);

    Ok(())
}

pub async fn drive_handshake<R>(conn: &mut TlsConnection<R>) {
    assert!(conn.async_handshake().await.unwrap().is_none());
}

#[test]
fn test_async_shutdown() -> Result<(), Error> {
    use futures::future::FutureExt;

    let (mut server_conn, mut client_conn) = dumb_server_client()?;

    let (client_socket, server_socket, mut executor) = create_mock_pipe();

    server_conn.set_io(server_socket)?;
    client_conn.set_io(client_socket)?;

    let test_future = async move {
        let server_handshake = drive_handshake(&mut server_conn);
        let client_handshake = drive_handshake(&mut client_conn);

        join(server_handshake, client_handshake).await;

        let (send_signal, recv_signal) = futures::channel::oneshot::channel::<()>();

        let server_fut = async move {
            // The following shutdown call should not make progress.
            let res = server_conn.as_pin_mut().async_shutdown().now_or_never();
            assert!(res.is_none());

            // Make the client progress.
            send_signal.send(()).unwrap();

            server_conn.as_pin_mut().async_shutdown().await.unwrap();
        };

        let client_fut = async move {
            recv_signal.await.unwrap();
            match client_conn.as_pin_mut().async_shutdown().await {
                Ok(_) | Err(Error::Io(crate::errors::IoError::EndOfStream)) => {}
                Err(e) => panic!("{e:?}"),
            }
        };

        join(server_fut, client_fut).await;
    };

    executor.run(test_future);

    Ok(())
}
