// 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 core::ptr::null_mut;

use bssl_x509::{
    params::CertificateVerificationParams,
    store::X509Store, //
};

use super::TlsContextBuilder;
use crate::{
    check_lib_error,
    config::ConfigurationError,
    context::{
        CertificateCache,
        SupportedMode,
        methods::{
            HasPrivateKeyMethods,
            RustContextMethods, //
        }, //
    },
    credentials::{
        CertificateType,
        CertificateVerificationMode,
        DistinguishedName,
        PrivateKeyDelegate,
        SignatureAlgorithm,
        TlsCredential,
        VerifyCertificate,
        cert_cb,
        early_callback::{
            EarlyCallback,
            early_cb, //
        }, //
        select_cert::{
            ClientCertificateSelector,
            ServerCertificateSelector,
            select_cert_cb, //
        },
    },
    errors::Error,
    ffi::slice_into_ffi_raw_parts,
    has_duplicates, //
};

/// # Credentials
impl<M> TlsContextBuilder<M>
where
    M: SupportedMode,
{
    /// Set the certificate cache.
    ///
    /// This [`CertificateCache`] can be shared across multiple contexts and their associated
    /// connections.
    /// The cache is recommended for use to reduce memory footprint arising from the X.509-based
    /// authentication.
    pub fn with_certificate_cache(&mut self, cache: Option<&CertificateCache>) -> &mut Self {
        let ctx = self.ptr();
        if let Some(cache) = cache {
            unsafe {
                // Safety: `CertificateCache` is `Send + Sync`
                bssl_sys::SSL_CTX_set1_buffer_pool(ctx, cache.ptr());
            }
        } else {
            unsafe {
                // Safety: we just detach the buffer pool before any active pointer into it is created.
                bssl_sys::SSL_CTX_set1_buffer_pool(ctx, null_mut());
            }
        }
        self
    }

    /// Set the private key method.
    ///
    /// This private key method delegation may be replaced the next moment when
    /// a new TLS private key is supplied.
    pub fn with_private_key_delegate(
        &mut self,
        key_method: Option<Box<dyn PrivateKeyDelegate>>,
    ) -> &mut Self {
        let ctx = self.ptr();
        if key_method.is_some() {
            unsafe {
                // Safety: we only install our own vtable.
                bssl_sys::SSL_CTX_set_private_key_method(ctx, <M as HasPrivateKeyMethods>::METHODS);
            }
        } else {
            unsafe {
                // Safety: we only uninstall the vtable.
                bssl_sys::SSL_CTX_set_private_key_method(ctx, core::ptr::null());
            }
        }
        self.get_context_methods().private_key_methods = key_method;
        self
    }

    /// Set certificate verification mode.
    ///
    /// # Client certificate verification for servers, mutual TLS
    ///
    /// Server can choose to request a certificate from the client by setting `mode` to
    /// - [`CertificateVerificationMode::PeerCertRequested`] which may still let handshake complete
    ///   if the certificate request by the server is not fulfilled.
    /// - [`CertificateVerificationMode::PeerCertMandatory`] which will abort handshake if
    ///   the request is not fulfilled.
    pub fn with_certificate_verification_mode(
        &mut self,
        mode: CertificateVerificationMode,
    ) -> &mut Self {
        let conn = self.ptr();
        unsafe {
            // Safety: we only install our own vtable.
            bssl_sys::SSL_CTX_set_verify(conn, mode as _, None);
        }
        self
    }

    /// Set certificate verification mode and custom verifier.
    ///
    /// # Setting custom certificate verifier
    ///
    /// See [`VerifyCertificate`] for how to implement a custom verifier.
    ///
    /// # Client certificate verification for servers, mutual TLS
    ///
    /// Server can choose to request a certificate from the client by setting `mode` to
    /// - [`CertificateVerificationMode::PeerCertRequested`] which may still let handshake complete
    ///   if the certificate request by the server is not fulfilled.
    /// - [`CertificateVerificationMode::PeerCertMandatory`] which will abort handshake if
    ///   the request is not fulfilled.
    pub fn with_certificate_verifier<V>(
        &mut self,
        mode: CertificateVerificationMode,
        verifier: V,
    ) -> &mut Self
    where
        V: VerifyCertificate + 'static,
    {
        let conn = self.ptr();
        unsafe {
            // Safety: we only install our own vtable.
            bssl_sys::SSL_CTX_set_custom_verify(
                conn,
                mode as _,
                Some(cert_cb::<super::methods::RustContextMethods<M>>),
            );
        }
        self.get_context_methods().verify_certificate_methods = Some(Box::new(verifier) as _);
        self
    }

    /// Remove custom certificate verifier.
    pub fn without_certificate_verifier(&mut self, mode: CertificateVerificationMode) -> &mut Self {
        let conn = self.ptr();
        unsafe {
            // Safety: we only uninstall the vtable.
            bssl_sys::SSL_CTX_set_custom_verify(conn, mode as _, None);
        }
        self.get_context_methods().verify_certificate_methods = None;
        self
    }

    /// Set custom certificate selection callback.
    ///
    /// See [`EarlyCallback`] for its semantics.
    pub fn with_early_callback<S>(&mut self, handler: S) -> &mut Self
    where
        S: EarlyCallback<M> + 'static,
    {
        let ctx = self.ptr();
        unsafe {
            // Safety: we only install our own vtable.
            bssl_sys::SSL_CTX_set_select_certificate_cb(
                ctx,
                Some(early_cb::<M, super::methods::RustContextMethods<M>>),
            );
        }
        self.get_context_methods().early_callback_handler = Some(Box::new(handler) as _);
        self
    }

    /// Remove custom certificate selection callback.
    pub fn without_early_callback(&mut self) -> &mut Self {
        let ctx = self.ptr();
        unsafe {
            // Safety: we only uninstall the vtable.
            bssl_sys::SSL_CTX_set_select_certificate_cb(ctx, None);
        }
        self.get_context_methods().early_callback_handler = None;
        self
    }

    /// Append `credential` to the list of credentials of this context.
    pub fn with_credential(&mut self, credential: TlsCredential) -> Result<&mut Self, Error> {
        check_lib_error!(unsafe {
            // Safety:
            // - the validity of the handle `self.0` is witnessed by `self`.
            // - the method will bump the refcount of the credential for ownership.
            bssl_sys::SSL_CTX_add1_credential(self.ptr(), credential.ptr())
        });
        Ok(self)
    }

    /// Set the list of accepted peer certificate types.
    pub fn with_accepted_peer_cert_types(
        &mut self,
        types: &[CertificateType],
    ) -> Result<&mut Self, Error> {
        let (ptr, len) = slice_into_ffi_raw_parts(types);
        check_lib_error!(unsafe {
            // Safety:
            // - `self.ptr()` is a valid `SSL_CTX` handle.
            // - `ptr` is a valid pointer to an array of `i32` representing certificate types.
            // - `len` is the number of elements in the array.
            // - The function copies the data, so the pointer only needs to be valid for the call.
            bssl_sys::SSL_CTX_set1_accepted_peer_cert_types(self.ptr(), ptr as *const _, len)
        });
        Ok(self)
    }

    /// Set the list of available client certificate types.
    pub fn with_available_client_cert_types(
        &mut self,
        types: &[CertificateType],
    ) -> Result<&mut Self, Error> {
        let (ptr, len) = slice_into_ffi_raw_parts(types);
        check_lib_error!(unsafe {
            // Safety:
            // - `self.ptr()` is a valid `SSL_CTX` handle.
            // - `ptr` is a valid pointer to an array of `i32` representing certificate types.
            // - `len` is the number of elements in the array.
            // - The function copies the data, so the pointer only needs to be valid for the call.
            bssl_sys::SSL_CTX_set1_available_client_cert_types(self.ptr(), ptr as *const _, len)
        });
        Ok(self)
    }
}

/// # Certificate selection
impl<M: SupportedMode> TlsContextBuilder<M> {
    /// Set certificate selection callback on **client** side.
    pub fn with_client_side_certificate_callback<T: 'static + ClientCertificateSelector<M>>(
        &mut self,
        cb: Option<T>,
    ) -> &mut Self {
        let ctx = self.ptr();
        let methods = self.get_context_methods();
        if let Some(cb) = cb {
            methods.client_cert_cb = Some(Box::new(cb) as _);
            unsafe {
                // Safety: we only install our own vtable.
                bssl_sys::SSL_CTX_set_cert_cb(
                    ctx,
                    Some(select_cert_cb::<RustContextMethods<M>, M>),
                    null_mut(),
                );
            }
        } else {
            methods.client_cert_cb = None;
            unsafe {
                // Safety: we only uninstall the vtable.
                bssl_sys::SSL_CTX_set_cert_cb(ctx, None, null_mut());
            }
        }
        self
    }

    /// Set certificate selection callback on **server** side.
    pub fn with_server_side_certificate_callback<T: 'static + ServerCertificateSelector<M>>(
        &mut self,
        cb: Option<T>,
    ) -> &mut Self {
        let ctx = self.ptr();
        let methods = self.get_context_methods();
        if let Some(cb) = cb {
            methods.server_cert_cb = Some(Box::new(cb) as _);
            unsafe {
                // Safety: we only install our own vtable.
                bssl_sys::SSL_CTX_set_cert_cb(
                    ctx,
                    Some(select_cert_cb::<RustContextMethods<M>, M>),
                    null_mut(),
                );
            }
        } else {
            methods.server_cert_cb = None;
            unsafe {
                // Safety: we only uninstall the vtable.
                bssl_sys::SSL_CTX_set_cert_cb(ctx, None, null_mut());
            }
        }
        self
    }
}

/// # Certificate verification, X.509
///
/// These methods require built-in X.509 support and are not available for
/// [`TlsExternalVerifierMode`](super::TlsExternalVerifierMode) or
/// [`DtlsExternalVerifierMode`](super::DtlsExternalVerifierMode).
impl<M> TlsContextBuilder<M>
where
    M: super::UseBuiltinX509,
{
    /// Set certificate verification parameters.
    pub fn with_certificate_verification_params(
        &mut self,
        params: &CertificateVerificationParams,
    ) -> Result<&mut Self, Error> {
        check_lib_error!(unsafe {
            // Safety:
            // - the validity of the handle `self.0` is witnessed by `self`.
            // - `SSL_CTX_set1_param` bumps the ref-count on the `params`.
            bssl_sys::SSL_CTX_set1_param(self.ptr(), params.as_ptr())
        });
        Ok(self)
    }

    /// Enable signed certificate timestamps.
    ///
    /// This method will instruct the client connections to request Signed Certificate Timestamps.
    /// See [RFC 6962] for more information.
    ///
    /// [RFC 6962]: https://datatracker.ietf.org/doc/html/rfc6962
    pub fn enable_signed_certificate_timestamps(&mut self) -> &mut Self {
        unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_enable_signed_cert_timestamps(self.ptr());
        }
        self
    }

    /// Set certificate verification store.
    pub fn with_certificate_store(&mut self, store: &X509Store) -> &mut Self {
        unsafe {
            // Safety:
            // - the validity of the handle `self.0` is witnessed by `self`.
            // - `SSL_CTX_set1_verify_cert_store` bumps the ref-count on `store`.
            assert_eq!(
                bssl_sys::SSL_CTX_set1_verify_cert_store(self.ptr(), store.as_mut_ptr()),
                1,
            );
        }
        self
    }
}

/// # Signature algorithm preferences
impl<M> TlsContextBuilder<M> {
    /// Set a preference list of signature algorithms for verification.
    ///
    /// This method returns [`ConfigurationError::InvalidParameters`] if the list of algorithms
    /// contains duplicate entries.
    pub fn with_signature_verification_algorithm_preferences(
        &mut self,
        algs: &[SignatureAlgorithm],
    ) -> Result<&mut Self, Error> {
        let algs: &[u16] = unsafe {
            // Safety: `SignatureAlgorithm` has a `repr(u16)` and maps to preferences correctly
            // by construction.
            core::mem::transmute(algs)
        };
        if has_duplicates(algs) {
            return Err(Error::Configuration(ConfigurationError::InvalidParameters));
        }

        let (prefs, prefs_len) = slice_into_ffi_raw_parts(algs);
        check_lib_error!(unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_set_verify_algorithm_prefs(self.ptr(), prefs, prefs_len)
        });
        Ok(self)
    }

    /// Set a preference list of algorithms for signing.
    ///
    /// This method returns [`ConfigurationError::InvalidParameters`] if the list of algorithms
    /// contains duplicate entries.
    pub fn with_signing_algorithm_preferences(
        &mut self,
        algs: &[SignatureAlgorithm],
    ) -> Result<&mut Self, Error> {
        let algs: &[u16] = unsafe {
            // Safety: `SignatureAlgorithm` has a `repr(u16)` and maps to preferences correctly
            // by construction.
            core::mem::transmute(algs)
        };
        if has_duplicates(algs) {
            return Err(Error::Configuration(ConfigurationError::InvalidParameters));
        }

        let (prefs, prefs_len) = slice_into_ffi_raw_parts(algs);
        check_lib_error!(unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_set_signing_algorithm_prefs(self.ptr(), prefs, prefs_len)
        });
        Ok(self)
    }
}

/// # Certificate authorities - Server
///
/// TLS can send a list of supported certificate authorities to guide the peer in certificate
/// selection.
impl<M> TlsContextBuilder<M> {
    /// This setting advertises the list of certificate authorities names in the
    /// `certificate_authorities` extension to send the client.
    pub fn set_ca_names(
        &mut self,
        names: impl IntoIterator<Item = DistinguishedName>,
    ) -> &mut Self {
        unsafe {
            // Safety: this call only transfers the ownership of the stack.
            bssl_sys::SSL_CTX_set0_client_CAs(
                self.ptr(),
                DistinguishedName::into_crypto_buffer_stack(names),
            )
        }
        self
    }
}
