// DTLS Server Handshake Flow:
//
// 1. Client sends ClientHello (maybe without cookie)
// 2. If cookie missing/invalid, Server sends HelloVerifyRequest (stateless cookie)
//    - Client resends ClientHello with cookie
// 3. Server sends ServerHello, Certificate, ServerKeyExchange,
//    CertificateRequest (required), ServerHelloDone
// 4. Client sends Certificate (optional), ClientKeyExchange,
//    CertificateVerify (if client cert), ChangeCipherSpec, Finished
// 5. Server verifies Finished, then sends ChangeCipherSpec, Finished
// 6. Handshake complete, application data can flow
//
// This implementation mirrors the client structure and ordering for a DTLS server.

use std::collections::VecDeque;
use std::sync::Arc;
use std::time::Instant;

use arrayvec::ArrayVec;
use subtle::ConstantTimeEq;

use rand::random;

use crate::buffer::{Buf, ToBuf};
use crate::client::LocalEvent;
use crate::crypto::SrtpProfile;
use crate::engine::Engine;
use crate::message::{Body, CertificateRequest, CipherSuite, ClientCertificateType};
use crate::message::{CompressionMethod, ContentType, Cookie, CurveType};
use crate::message::{DistinguishedName, ExchangeKeys, ExtensionType};
use crate::message::{HashAlgorithm, HelloVerifyRequest, KeyExchangeAlgorithm};
use crate::message::{MessageType, NamedGroup, ProtocolVersion, Random, ServerHello};
use crate::message::{SessionId, SignatureAlgorithm};
use crate::message::{SignatureAlgorithmsExtension, SignatureAndHashAlgorithm, SrtpProfileId};
use crate::message::{SupportedGroupsExtension, UseSrtpExtension};
use crate::{Client, Config, Error, Output};

/// DTLS server
pub struct Server {
    /// Current server state.
    state: State,

    /// Engine in common between server and client.
    engine: Engine,

    /// Random unique data (with gmt timestamp). Used for signature checks.
    random: Option<Random>,

    /// SessionId we provide to the client (unused/resumption not implemented).
    session_id: Option<SessionId>,

    /// Cookie secret for HMAC, generated per-server instance
    cookie_secret: [u8; 32],

    /// Storage for extension data
    extension_data: Buf,

    /// The negotiated SRTP profile (if any)
    negotiated_srtp_profile: Option<SrtpProfile>,

    /// Client's offered supported_groups (if any)
    client_supported_groups: Option<ArrayVec<NamedGroup, 16>>,

    /// Client's offered signature_algorithms (if any)
    client_signature_algorithms: Option<ArrayVec<SignatureAndHashAlgorithm, 32>>,

    /// Client random. Set by ClientHello.
    client_random: Option<Random>,

    /// Client certificates
    client_certificates: Vec<Buf>,

    /// Buffer for defragmenting handshakes
    defragment_buffer: Buf,

    /// Captured session hash for Extended Master Secret (RFC 7627)
    captured_session_hash: Option<Buf>,

    /// The last now we seen
    last_now: Option<Instant>,

    /// Events we are to emit from this Server.
    local_events: VecDeque<LocalEvent>,

    /// Data that is sent before we are connected.
    queued_data: Vec<Buf>,
}

/// Current state of the server.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
    AwaitClientHello,
    SendServerHello,
    SendCertificate,
    SendServerKeyExchange,
    SendCertificateRequest,
    SendServerHelloDone,
    AwaitCertificate,
    AwaitClientKeyExchange,
    AwaitCertificateVerify,
    AwaitChangeCipherSpec,
    AwaitFinished,
    SendChangeCipherSpec,
    SendFinished,
    AwaitApplicationData,
}

impl Server {
    /// Create a new DTLS server
    pub fn new(config: Arc<Config>, certificate: crate::DtlsCertificate) -> Server {
        let engine = Engine::new(config, certificate);
        Self::new_with_engine(engine)
    }

    pub(crate) fn new_with_engine(mut engine: Engine) -> Server {
        engine.set_client(false);

        let cookie_secret: [u8; 32] = random();

        Server {
            state: State::AwaitClientHello,
            engine,
            random: None,
            session_id: None,
            cookie_secret,
            extension_data: Buf::new(),
            negotiated_srtp_profile: None,
            client_supported_groups: None,
            client_signature_algorithms: None,
            client_random: None,
            client_certificates: Vec::with_capacity(3),
            defragment_buffer: Buf::new(),
            captured_session_hash: None,
            last_now: None,
            local_events: VecDeque::new(),
            queued_data: Vec::new(),
        }
    }

    pub fn into_client(self) -> Client {
        Client::new_with_engine(self.engine)
    }

    pub fn handle_packet(&mut self, packet: &[u8]) -> Result<(), Error> {
        self.engine.parse_packet(packet)?;
        self.make_progress()?;
        Ok(())
    }

    pub fn poll_output<'a>(&mut self, buf: &'a mut [u8]) -> Output<'a> {
        let last_now = self
            .last_now
            .expect("need handle_timeout before poll_output");

        if let Some(event) = self.local_events.pop_front() {
            return event.into_output(buf, &self.client_certificates);
        }

        self.engine.poll_output(buf, last_now)
    }

    pub fn handle_timeout(&mut self, now: Instant) -> Result<(), Error> {
        self.last_now = Some(now);
        if self.random.is_none() {
            self.random = Some(Random::new(now));
        }
        self.engine.handle_timeout(now)?;
        self.make_progress()?;
        Ok(())
    }

    /// Send application data when the server is in the Running state
    pub fn send_application_data(&mut self, data: &[u8]) -> Result<(), Error> {
        if self.state != State::AwaitApplicationData {
            self.queued_data.push(data.to_buf());
            return Ok(());
        }

        // Use the engine's create_record to send application data
        // The encryption is now handled in the engine
        self.engine
            .create_record(ContentType::ApplicationData, 1, false, |body| {
                body.extend_from_slice(data);
            })?;

        Ok(())
    }

    fn make_progress(&mut self) -> Result<(), Error> {
        loop {
            let prev_state = self.state;

            let new_state = prev_state.make_progress(self)?;
            if prev_state != new_state {
                self.state = new_state;
                trace!("{:?} -> {:?}", prev_state, new_state);
            } else {
                break;
            }
        }
        Ok(())
    }
}

impl State {
    fn make_progress(self, server: &mut Server) -> Result<Self, Error> {
        match self {
            State::AwaitClientHello => self.await_client_hello(server),
            State::SendServerHello => self.send_server_hello(server),
            State::SendCertificate => self.send_certificate(server),
            State::SendServerKeyExchange => self.send_server_key_exchange(server),
            State::SendCertificateRequest => self.send_certificate_request(server),
            State::SendServerHelloDone => self.send_server_hello_done(server),
            State::AwaitCertificate => self.await_certificate(server),
            State::AwaitClientKeyExchange => self.await_client_key_exchange(server),
            State::AwaitCertificateVerify => self.await_certificate_verify(server),
            State::AwaitChangeCipherSpec => self.await_change_cipher_spec(server),
            State::AwaitFinished => self.await_finished(server),
            State::SendChangeCipherSpec => self.send_change_cipher_spec(server),
            State::SendFinished => self.send_finished(server),
            State::AwaitApplicationData => self.await_application_data(server),
        }
    }

    fn await_client_hello(self, server: &mut Server) -> Result<Self, Error> {
        let maybe = server
            .engine
            .next_handshake(MessageType::ClientHello, &mut server.defragment_buffer)?;

        let Some(handshake) = maybe else {
            // Stay in same state
            return Ok(self);
        };

        let Body::ClientHello(ch) = handshake.body else {
            unreachable!()
        };

        // Enforce DTLS1.2
        if ch.client_version != ProtocolVersion::DTLS1_2 {
            return Err(Error::SecurityError(format!(
                "Unsupported DTLS version from client: {:?}",
                ch.client_version
            )));
        }

        // Enforce Null compression only (client must offer it)
        let has_null = ch.compression_methods.contains(&CompressionMethod::Null);
        if !has_null {
            return Err(Error::SecurityError(
                "Client did not offer Null compression".to_string(),
            ));
        }

        trace!(
            "ClientHello: cookie_len={}, offered_suites={}",
            ch.cookie.len(),
            ch.cipher_suites.len()
        );

        // Stateless cookie: require 32-byte cookie matching HMAC(secret, client_random)
        let client_random = ch.random;
        let hmac_provider = server.engine.config().crypto_provider().hmac_provider;
        if !verify_cookie(
            hmac_provider,
            &server.cookie_secret,
            client_random,
            ch.cookie,
        ) {
            debug!("Invalid/missing cookie; sending HelloVerifyRequest");

            let cookie = compute_cookie(hmac_provider, &server.cookie_secret, client_random)?;
            // Start/restart flight timer for server Flight 2 (HelloVerifyRequest)
            server.engine.flight_begin(2);
            server
                .engine
                .create_handshake(MessageType::HelloVerifyRequest, |body, _engine| {
                    let hvr = HelloVerifyRequest::new(ProtocolVersion::DTLS1_2, cookie);
                    hvr.serialize(body);
                    Ok(())
                })?;

            // The HelloVerifyRequest exchange is not part of the main handshake transcript.
            // Clear transcript so subsequent CertificateVerify/Finished cover only the real handshake.
            server.engine.transcript_reset();
            return Ok(self);
        }

        trace!("Accepted ClientHello cookie; proceeding with handshake");

        // Client offered suites; we pick per client order intersecting allowed and server key compatibility
        let mut selected: Option<CipherSuite> = None;
        for s in ch.cipher_suites.iter() {
            let is_allowed = server.engine.is_cipher_suite_allowed(*s);
            let is_compatible = server
                .engine
                .crypto_context()
                .is_cipher_suite_compatible(*s);
            if is_allowed && is_compatible {
                selected = Some(*s);
                break;
            }
        }

        let Some(cs) = selected else {
            return Err(Error::SecurityError(
                "No mutually acceptable cipher suite".to_string(),
            ));
        };

        server.engine.set_cipher_suite(cs);
        server.client_random = Some(client_random);

        debug!("Selected cipher suite: {:?}", cs);

        // Process client extensions: SRTP, EMS, SupportedGroups and SignatureAlgorithms
        let mut client_offers_ems = false;
        let mut client_srtp_profiles: Option<ArrayVec<SrtpProfileId, 32>> = None;
        let mut client_supported_groups: Option<ArrayVec<NamedGroup, 16>> = None;
        let mut client_signature_algorithms: Option<ArrayVec<SignatureAndHashAlgorithm, 32>> = None;
        for ext in ch.extensions {
            match ext.extension_type {
                ExtensionType::UseSrtp => {
                    let ext_data = ext.extension_data(&server.defragment_buffer);
                    if let Ok((_, use_srtp)) = UseSrtpExtension::parse(ext_data) {
                        client_srtp_profiles = Some(use_srtp.profiles);
                    } else {
                        warn!("Failed to parse UseSrtp extension");
                    }
                }
                ExtensionType::ExtendedMasterSecret => {
                    client_offers_ems = true;
                }
                ExtensionType::SupportedGroups => {
                    let ext_data = ext.extension_data(&server.defragment_buffer);
                    if let Ok((_, groups)) = SupportedGroupsExtension::parse(ext_data) {
                        client_supported_groups = Some(groups.groups);
                    } else {
                        warn!("Failed to parse SupportedGroups extension");
                    }
                }
                ExtensionType::SignatureAlgorithms => {
                    let ext_data = ext.extension_data(&server.defragment_buffer);
                    if let Ok((_, sigs)) = SignatureAlgorithmsExtension::parse(ext_data) {
                        client_signature_algorithms = Some(sigs.supported_signature_algorithms);
                    } else {
                        warn!("Failed to parse SignatureAlgorithms extension");
                    }
                }
                _ => {}
            }
        }

        // EMS is mandatory
        if !client_offers_ems {
            return Err(Error::SecurityError(
                "Extended Master Secret not negotiated".to_string(),
            ));
        }

        // Select SRTP profile according to server priority: AES256GCM, AES128GCM, then SHA1
        if let Some(profiles) = client_srtp_profiles {
            // Map client profile ids to SrtpProfile, then pick our preferred
            let mut selected_profile: Option<SrtpProfile> = None;
            for preferred in [
                SrtpProfile::AeadAes256Gcm,
                SrtpProfile::AeadAes128Gcm,
                SrtpProfile::Aes128CmSha1_80,
            ] {
                if profiles.iter().any(|pid| preferred == (*pid).into()) {
                    selected_profile = Some(preferred);
                    break;
                }
            }
            server.negotiated_srtp_profile = selected_profile;
            if let Some(profile) = server.negotiated_srtp_profile {
                debug!("Negotiated SRTP profile: {:?}", profile);
            }
        }

        // Store client's offers for later selection
        server.client_supported_groups = client_supported_groups;
        server.client_signature_algorithms = client_signature_algorithms;

        // Proceed to send the server flight
        trace!("Extended Master Secret enabled");
        Ok(Self::SendServerHello)
    }

    fn send_server_hello(self, server: &mut Server) -> Result<Self, Error> {
        trace!("Sending ServerHello");

        // Start/restart flight timer for server Flight 4
        server.engine.flight_begin(4);

        let session_id = server.session_id.unwrap_or_else(SessionId::empty);
        // unwrap: is ok because we set the random in handle_timeout
        let random = server.random.unwrap();
        let negotiated_srtp_profile = server.negotiated_srtp_profile;
        let extension_data = &mut server.extension_data;

        // Send ServerHello
        server
            .engine
            .create_handshake(MessageType::ServerHello, move |body, engine| {
                handshake_create_server_hello(
                    body,
                    engine,
                    random,
                    session_id,
                    negotiated_srtp_profile,
                    extension_data,
                )
            })?;

        Ok(Self::SendCertificate)
    }

    fn send_certificate(self, server: &mut Server) -> Result<Self, Error> {
        trace!("Sending Certificate");

        server
            .engine
            .create_handshake(MessageType::Certificate, handshake_create_certificate)?;

        Ok(Self::SendServerKeyExchange)
    }

    fn send_server_key_exchange(self, server: &mut Server) -> Result<Self, Error> {
        trace!("Sending ServerKeyExchange");

        let client_random = server
            .client_random
            .ok_or_else(|| Error::UnexpectedMessage("No client random".to_string()))?;
        // unwrap: is ok because we set the random in handle_timeout
        let server_random = server.random.unwrap();

        // Select ECDHE group from client offers (prefer P-256, then P-384).
        // If none present, default to P-256.
        let selected_named_group = select_named_group(server.client_supported_groups.as_ref());

        // Select signature/hash for SKE by intersecting client's list
        // with our key type (prefer SHA256, then SHA384)
        let selected_signature = select_ske_signature_algorithm(
            server.client_signature_algorithms.as_ref(),
            server.engine.crypto_context().signature_algorithm(),
        );

        debug!(
            "ServerKeyExchange params: group={:?}, signature_alg={:?}",
            selected_named_group, selected_signature
        );

        server
            .engine
            .create_handshake(MessageType::ServerKeyExchange, |body, engine| {
                handshake_create_server_key_exchange(
                    body,
                    engine,
                    client_random,
                    server_random,
                    selected_named_group,
                    selected_signature,
                )
            })?;

        if server.engine.config().require_client_certificate() {
            Ok(Self::SendCertificateRequest)
        } else {
            Ok(Self::SendServerHelloDone)
        }
    }

    fn send_certificate_request(self, server: &mut Server) -> Result<Self, Error> {
        debug!("Sending CertificateRequest");
        // Select CertificateRequest.signature_algorithms as intersection of client's list and our supported
        let sig_algs =
            select_certificate_request_sig_algs(server.client_signature_algorithms.as_ref());
        debug!(
            "CertificateRequest will advertise {} signature algorithms",
            sig_algs.len()
        );

        server
            .engine
            .create_handshake(MessageType::CertificateRequest, move |body, _| {
                handshake_serialize_certificate_request(body, &sig_algs)
            })?;

        Ok(Self::SendServerHelloDone)
    }

    fn send_server_hello_done(self, server: &mut Server) -> Result<Self, Error> {
        trace!("Sending ServerHelloDone");

        server
            .engine
            .create_handshake(MessageType::ServerHelloDone, |_, _| Ok(()))?;

        if server.engine.config().require_client_certificate() {
            Ok(Self::AwaitCertificate)
        } else {
            Ok(Self::AwaitClientKeyExchange)
        }
    }

    fn await_certificate(self, server: &mut Server) -> Result<Self, Error> {
        let maybe = server
            .engine
            .next_handshake(MessageType::Certificate, &mut server.defragment_buffer)?;

        let Some(ref handshake) = maybe else {
            // Stay in same state
            return Ok(self);
        };

        let Body::Certificate(certificate) = &handshake.body else {
            unreachable!()
        };

        // Extract certificate ranges before dropping handshake
        let cert_ranges: ArrayVec<_, 32> = certificate
            .certificate_list
            .iter()
            .map(|cert| cert.0.clone())
            .collect();

        drop(maybe);

        if cert_ranges.is_empty() {
            // Client didn't provide a certificate (allowed), skip
        } else {
            // Store and verify via callback
            debug!(
                "Received client certificate chain with {} certificate(s)",
                cert_ranges.len()
            );
            for (i, range) in cert_ranges.iter().enumerate() {
                let cert_data = &server.defragment_buffer[range.clone()];
                trace!(
                    "Client Certificate #{} size: {} bytes",
                    i + 1,
                    cert_data.len()
                );
                server.client_certificates.push(cert_data.to_buf());
            }

            server.local_events.push_back(LocalEvent::PeerCert);
        }

        Ok(Self::AwaitClientKeyExchange)
    }

    fn await_client_key_exchange(self, server: &mut Server) -> Result<Self, Error> {
        let maybe = server.engine.next_handshake(
            MessageType::ClientKeyExchange,
            &mut server.defragment_buffer,
        )?;

        let Some(ref handshake) = maybe else {
            // Stay in same state
            return Ok(self);
        };

        let Body::ClientKeyExchange(ckx) = &handshake.body else {
            unreachable!()
        };

        let suite = server
            .engine
            .cipher_suite()
            .ok_or_else(|| Error::UnexpectedMessage("No cipher suite selected".to_string()))?;

        // Extract client's public key range before dropping handshake
        let public_key_range = match &ckx.exchange_keys {
            ExchangeKeys::Ecdh(keys) => keys.public_key_range.clone(),
        };

        drop(maybe);

        // Get the actual public key data from defragment_buffer
        let client_pub = &server.defragment_buffer[public_key_range];

        // Compute shared secret
        let mut buf = server.engine.pop_buffer();
        server
            .engine
            .crypto_context_mut()
            .compute_shared_secret(client_pub, &mut buf)
            .map_err(|e| Error::CryptoError(format!("Failed to compute shared secret: {}", e)))?;

        // Capture session hash for EMS now (up to ClientKeyExchange)
        let suite_hash = suite.hash_algorithm();
        server.engine.transcript_hash(suite_hash, &mut buf);
        server.captured_session_hash = Some(buf);

        // Derive master secret and keys (needed to decrypt client's Finished)
        let suite_hash = suite.hash_algorithm();
        let client_random_buf = {
            let mut b = Buf::new();
            server.client_random.unwrap().serialize(&mut b);
            b
        };
        let server_random_buf = {
            let mut b = Buf::new();
            // unwrap: is ok because we set the random in handle_timeout
            server.random.unwrap().serialize(&mut b);
            b
        };

        let session_hash = server.captured_session_hash.as_ref().ok_or_else(|| {
            Error::CryptoError(
                "Extended Master Secret negotiated but session hash not captured".to_string(),
            )
        })?;

        let mut out = server.engine.pop_buffer();
        let mut scratch = server.engine.pop_buffer();
        server
            .engine
            .crypto_context_mut()
            .derive_extended_master_secret(session_hash, suite_hash, &mut out, &mut scratch)
            .map_err(|e| {
                Error::CryptoError(format!("Failed to derive extended master secret: {}", e))
            })?;

        server
            .engine
            .crypto_context_mut()
            .derive_keys(
                suite,
                &client_random_buf,
                &server_random_buf,
                &mut out,
                &mut scratch,
            )
            .map_err(|e| Error::CryptoError(format!("Failed to derive keys: {}", e)))?;

        server.engine.push_buffer(out);
        server.engine.push_buffer(scratch);

        trace!(
            "Captured session hash length for EMS: {}",
            session_hash.len()
        );
        trace!("Derived session keys (EMS) and ready to verify Finished");

        if !server.client_certificates.is_empty() {
            Ok(Self::AwaitCertificateVerify)
        } else {
            Ok(Self::AwaitChangeCipherSpec)
        }
    }

    fn await_certificate_verify(self, server: &mut Server) -> Result<Self, Error> {
        // Get handshake data BEFORE processing CertificateVerify message
        // According to TLS spec, signature is over all handshake messages up to but not including CertificateVerify
        let data = server.engine.transcript().to_buf();

        let maybe = server.engine.next_handshake(
            MessageType::CertificateVerify,
            &mut server.defragment_buffer,
        )?;

        if maybe.is_none() {
            // Stay in same state
            return Ok(self);
        };

        // Extract signature data before accessing buffer
        let (signature_range, signature_algorithm) = {
            let handshake = maybe.as_ref().unwrap();
            let Body::CertificateVerify(cv) = &handshake.body else {
                unreachable!()
            };

            (cv.signed.signature_range.clone(), cv.signed.algorithm)
        };

        // Drop maybe to release buffer borrow
        drop(maybe);

        // Now access the buffer
        let signature_bytes = &server.defragment_buffer[signature_range];

        if server.client_certificates.is_empty() {
            return Err(Error::CertificateError(
                "CertificateVerify received but no client certificate".to_string(),
            ));
        }

        // Create temp DigitallySigned for verification
        let temp_signed = crate::message::DigitallySigned {
            algorithm: signature_algorithm,
            signature_range: 0..signature_bytes.len(),
        };

        server
            .engine
            .crypto_context()
            .verify_signature(
                &data,
                &temp_signed,
                signature_bytes,
                &server.client_certificates[0],
            )
            .map_err(|e| {
                Error::CryptoError(format!("Failed to verify client CertificateVerify: {}", e))
            })?;

        debug!("Client CertificateVerify verified successfully");

        Ok(Self::AwaitChangeCipherSpec)
    }

    fn await_change_cipher_spec(self, server: &mut Server) -> Result<Self, Error> {
        let maybe = server.engine.next_record(ContentType::ChangeCipherSpec);

        let Some(_) = maybe else {
            // Stay in same state
            return Ok(self);
        };

        // Drop any extra CCS resends to avoid being blocked
        trace!("Dropping any pending CCS resends from peer");
        server.engine.drop_pending_ccs();

        // Expect every record to be decrypted from now on.
        trace!("Received ChangeCipherSpec; enabling peer encryption");
        server.engine.enable_peer_encryption()?;

        Ok(Self::AwaitFinished)
    }

    fn await_finished(self, server: &mut Server) -> Result<Self, Error> {
        // Generate expected verify data based on current transcript.
        // This must be done before next_handshake() below since
        // it should not include Finished itself.
        let expected = server.engine.generate_verify_data(true /* client */)?;

        let maybe = server
            .engine
            .next_handshake(MessageType::Finished, &mut server.defragment_buffer)?;

        if maybe.is_none() {
            // stay in same state
            return Ok(self);
        }

        // Extract the range from the handshake
        let verify_data_range = if let Some(ref handshake) = maybe {
            if let Body::Finished(finished) = &handshake.body {
                finished.verify_data_range.clone()
            } else {
                panic!("Finished message should have been parsed");
            }
        } else {
            unreachable!()
        };

        // Drop maybe to release the buffer borrow
        drop(maybe);

        // Now we can access the buffer
        let verify_data = &server.defragment_buffer[verify_data_range];
        // Use constant-time comparison to prevent timing attacks
        let is_eq: bool = verify_data.ct_eq(expected.as_slice()).into();
        if !is_eq {
            return Err(Error::SecurityError(
                "Client Finished verification failed".to_string(),
            ));
        }

        trace!("Client Finished verified successfully");

        Ok(Self::SendChangeCipherSpec)
    }

    fn send_change_cipher_spec(self, server: &mut Server) -> Result<Self, Error> {
        trace!("Sending ChangeCipherSpec");

        // Start/restart flight timer for server Flight 6 (CCS+Finished)
        server.engine.flight_begin(6);

        // Send ChangeCipherSpec
        server
            .engine
            .create_record(ContentType::ChangeCipherSpec, 0, true, |body| {
                body.push(1);
            })?;

        Ok(Self::SendFinished)
    }

    fn send_finished(self, server: &mut Server) -> Result<Self, Error> {
        trace!("Sending Finished message to complete handshake");

        server
            .engine
            .create_handshake(MessageType::Finished, |body, engine| {
                let verify_data = engine.generate_verify_data(false /* server */)?;
                trace!("Finished.verify_data length: {}", verify_data.len());
                // Directly write the verify data without creating Finished struct
                body.extend_from_slice(&verify_data);
                Ok(())
            })?;

        // Final flight sent; stop periodic retransmission timers per RFC 6347 FINISHED state.
        // If this flight need resending, it relies on the client to resend its last flight.
        server.engine.flight_stop_resend_timers();

        // Handshake complete
        debug!("Handshake complete; ready for application data");
        server.local_events.push_back(LocalEvent::Connected);

        // Emit SRTP keying material if negotiated
        if let Some(profile) = server.negotiated_srtp_profile {
            let suite_hash = server.engine.cipher_suite().unwrap().hash_algorithm();
            let mut out = server.engine.pop_buffer();
            let mut scratch = server.engine.pop_buffer();
            if let Ok(keying_material) = server
                .engine
                .crypto_context()
                .extract_srtp_keying_material(profile, suite_hash, &mut out, &mut scratch)
            {
                server.engine.push_buffer(out);
                server.engine.push_buffer(scratch);
                debug!(
                    "SRTP keying material extracted ({} bytes) for profile: {:?}",
                    keying_material.len(),
                    profile
                );
                // expect should be correct here since we negotiated the profile
                let profile = server
                    .negotiated_srtp_profile
                    .expect("SRTP profile should be negotiated");
                server
                    .local_events
                    .push_back(LocalEvent::KeyingMaterial(keying_material, profile));
            } else {
                server.engine.push_buffer(out);
                server.engine.push_buffer(scratch);
            }
        }

        server.engine.release_application_data();

        Ok(Self::AwaitApplicationData)
    }

    fn await_application_data(self, server: &mut Server) -> Result<Self, Error> {
        // Now send any application data that was queued before we were connected.
        if !server.queued_data.is_empty() {
            debug!(
                "Sending queued application data: {}",
                server.queued_data.len()
            );
            for data in server.queued_data.drain(..) {
                server
                    .engine
                    .create_record(ContentType::ApplicationData, 1, false, |body| {
                        body.extend_from_slice(&data);
                    })?;
            }
        }

        Ok(self)
    }
}

fn compute_cookie(
    hmac_provider: &dyn crate::crypto::HmacProvider,
    secret: &[u8],
    client_random: Random,
) -> Result<Cookie, Error> {
    // cookie = trunc_32(HMAC(secret, client_random))
    let mut buf = Buf::new();
    client_random.serialize(&mut buf);
    let tag = hmac_provider
        .hmac_sha256(secret, &buf)
        .map_err(|e| Error::CryptoError(format!("Failed to compute HMAC: {}", e)))?;
    let cookie = Cookie::try_new(&tag)
        .map_err(|_| Error::CryptoError("Failed to build cookie from HMAC output".to_string()))?;
    Ok(cookie)
}

fn verify_cookie(
    hmac_provider: &dyn crate::crypto::HmacProvider,
    secret: &[u8],
    client_random: Random,
    cookie: Cookie,
) -> bool {
    if cookie.len() != 32 {
        return false;
    }
    match compute_cookie(hmac_provider, secret, client_random) {
        // Use constant-time comparison to prevent timing attacks
        Ok(expected) => expected.as_ref().ct_eq(cookie.as_ref()).into(),
        Err(_) => false,
    }
}

fn handshake_create_certificate(body: &mut Buf, engine: &mut Engine) -> Result<(), Error> {
    let crypto = engine.crypto_context();
    crypto.serialize_client_certificate(body);
    Ok(())
}

fn handshake_create_server_hello(
    body: &mut Buf,
    engine: &mut Engine,
    random: Random,
    session_id: SessionId,
    negotiated_srtp_profile: Option<SrtpProfile>,
    extension_data: &mut Buf,
) -> Result<(), Error> {
    let server_version = ProtocolVersion::DTLS1_2;

    let cs = engine
        .cipher_suite()
        .ok_or_else(|| Error::UnexpectedMessage("No cipher suite".to_string()))?;

    let srtp_pid = negotiated_srtp_profile.map(|p| match p {
        SrtpProfile::AeadAes256Gcm => SrtpProfileId::SrtpAeadAes256Gcm,
        SrtpProfile::AeadAes128Gcm => SrtpProfileId::SrtpAeadAes128Gcm,
        SrtpProfile::Aes128CmSha1_80 => SrtpProfileId::SrtpAes128CmSha1_80,
    });

    let sh = ServerHello::new(
        server_version,
        random,
        session_id,
        cs,
        CompressionMethod::Null,
        None,
    )
    .with_extensions(extension_data, srtp_pid);

    sh.serialize(extension_data, body);
    Ok(())
}

fn handshake_create_server_key_exchange(
    body: &mut Buf,
    engine: &mut Engine,
    client_random: Random,
    server_random: Random,
    named_group: NamedGroup,
    algorithm: SignatureAndHashAlgorithm,
) -> Result<(), Error> {
    let Some(cipher_suite) = engine.cipher_suite() else {
        return Err(Error::UnexpectedMessage(
            "No cipher suite selected".to_string(),
        ));
    };

    let key_exchange_algorithm = cipher_suite.as_key_exchange_algorithm();
    debug!("Using key exchange algorithm: {:?}", key_exchange_algorithm);

    // Use hash part from selected algorithm
    let hash_alg = algorithm.hash;

    match key_exchange_algorithm {
        KeyExchangeAlgorithm::EECDH => {
            let (curve_type, named_group) = (CurveType::NamedCurve, named_group);
            let mut kx_buf = engine.pop_buffer();
            let pubkey = engine
                .crypto_context_mut()
                .init_ecdh_server(named_group, &mut kx_buf)
                .map_err(|e| Error::CryptoError(format!("Failed to init ECDHE: {}", e)))?;

            trace!(
                "SKE ECDHE: group={:?}, pubkey_len={}",
                named_group,
                pubkey.len()
            );

            // Build signed_data = client_random || server_random || params(without signature)
            let mut signed_data = Buf::new();
            client_random.serialize(&mut signed_data);
            server_random.serialize(&mut signed_data);
            // Write params directly for signing
            signed_data.push(curve_type.as_u8());
            signed_data.extend_from_slice(&named_group.as_u16().to_be_bytes());
            signed_data.push(pubkey.len() as u8);
            signed_data.extend_from_slice(pubkey);

            engine.push_buffer(kx_buf);

            let mut signature = engine.pop_buffer();

            trace!("SKE signature hash: {:?}", hash_alg);
            engine
                .crypto_context
                .sign_data(&signed_data, hash_alg, &mut signature)
                .map_err(|e| {
                    Error::CryptoError(format!("Failed to sign server key exchange: {}", e))
                })?;

            // unwrap: safe because init_ecdh_server() above sets key_exchange = Some(...).
            // If that failed, we returned Err earlier and never reach this point.
            let pubkey = engine
                .crypto_context_mut()
                .maybe_init_key_exchange()
                .unwrap();

            // For sending, we don't use DigitallySigned struct, just write the params and signature directly
            body.push(curve_type.as_u8());
            body.extend_from_slice(&named_group.as_u16().to_be_bytes());
            body.push(pubkey.len() as u8);
            body.extend_from_slice(pubkey);

            // Write signature
            body.extend_from_slice(&algorithm.as_u16().to_be_bytes());
            body.extend_from_slice(&(signature.len() as u16).to_be_bytes());
            body.extend_from_slice(&signature);

            engine.push_buffer(signature);

            Ok(())
        }
        _ => Err(Error::SecurityError(
            "Unsupported key exchange algorithm".to_string(),
        )),
    }
}

fn handshake_serialize_certificate_request(
    body: &mut Buf,
    sig_algs: &ArrayVec<SignatureAndHashAlgorithm, 32>,
) -> Result<(), Error> {
    // Advertise RSA_SIGN and ECDSA_SIGN; empty CA list
    let mut cert_types = ArrayVec::new();
    cert_types.push(ClientCertificateType::RSA_SIGN);
    cert_types.push(ClientCertificateType::ECDSA_SIGN);

    // If intersection is empty (e.g., client didn't advertise), fall back to our supported set
    // Build the selected list with the capacity expected by CertificateRequest
    let mut selected: ArrayVec<SignatureAndHashAlgorithm, 32> = ArrayVec::new();
    if sig_algs.is_empty() {
        let fallback = SignatureAndHashAlgorithm::supported();
        for alg in fallback.iter() {
            selected.push(*alg);
        }
    } else {
        for alg in sig_algs.iter() {
            selected.push(*alg);
        }
    }

    let cert_auths: ArrayVec<DistinguishedName, 32> = ArrayVec::new();

    let cr = CertificateRequest::new(cert_types, selected, cert_auths);
    cr.serialize(&[], body);
    Ok(())
}

fn select_named_group(client_groups: Option<&ArrayVec<NamedGroup, 16>>) -> NamedGroup {
    // Server preference order
    let preferred = [NamedGroup::Secp256r1, NamedGroup::Secp384r1];
    if let Some(groups) = client_groups {
        for p in preferred.iter() {
            if groups.iter().any(|g| g == p) {
                return *p;
            }
        }
    }
    // Fallback if client did not advertise groups or only unsupported ones
    NamedGroup::Secp256r1
}

fn select_ske_signature_algorithm(
    client_algs: Option<&ArrayVec<SignatureAndHashAlgorithm, 32>>,
    our_sig: SignatureAlgorithm,
) -> SignatureAndHashAlgorithm {
    // Our hash preference order
    let hash_pref = [HashAlgorithm::SHA256, HashAlgorithm::SHA384];

    if let Some(list) = client_algs {
        for h in hash_pref.iter() {
            if let Some(chosen) = list
                .iter()
                .find(|alg| alg.signature == our_sig && alg.hash == *h)
            {
                return *chosen;
            }
        }
    }

    // Fallback to our default hash for our key type
    let hash = engine_default_hash_for_sig(our_sig);
    SignatureAndHashAlgorithm::new(hash, our_sig)
}

fn engine_default_hash_for_sig(sig: SignatureAlgorithm) -> HashAlgorithm {
    match sig {
        SignatureAlgorithm::RSA => HashAlgorithm::SHA256,
        SignatureAlgorithm::ECDSA => HashAlgorithm::SHA256,
        _ => HashAlgorithm::SHA256,
    }
}

fn select_certificate_request_sig_algs(
    client_algs: Option<&ArrayVec<SignatureAndHashAlgorithm, 32>>,
) -> ArrayVec<SignatureAndHashAlgorithm, 32> {
    // Our supported set (RSA/ECDSA with SHA256/384)
    let ours = SignatureAndHashAlgorithm::supported();

    // Build intersection preserving client preference order
    let mut out = ArrayVec::new();
    if let Some(list) = client_algs {
        for alg in list.iter() {
            if ours
                .iter()
                .any(|a| a.hash == alg.hash && a.signature == alg.signature)
            {
                out.push(*alg);
            }
        }
    }
    out
}
