// 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 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(())
}
