use std::time::Duration;

use uuid::Uuid;

use crate::pipe::protocol::{supported_actions, AgentMessage, BrowserMessage, PROTOCOL_VERSION};
use crate::pipe::{PipeError, Transport};
use crate::security::derive_session_key;

#[derive(Debug, Clone)]
pub struct HandshakeResult {
    pub agent_id: String,
    pub session_key: Vec<u8>,
    pub capabilities: Vec<String>,
}

pub fn perform_handshake<T: Transport>(
    transport: &T,
    timeout: Duration,
) -> Result<HandshakeResult, PipeError> {
    let init = transport.recv_timeout(timeout)?;

    match init {
        BrowserMessage::Init {
            version,
            hmac_seed,
            capabilities,
        } => {
            if version != PROTOCOL_VERSION {
                return Err(PipeError::Protocol(format!(
                    "unsupported protocol version: {version}"
                )));
            }

            let session_key = derive_session_key(&hmac_seed)?;
            let agent_id = Uuid::new_v4().to_string();
            let ack = AgentMessage::InitAck {
                version: PROTOCOL_VERSION.to_string(),
                agent_id: agent_id.clone(),
                supported_actions: supported_actions(),
            };
            transport.send(&ack)?;

            Ok(HandshakeResult {
                agent_id,
                session_key,
                capabilities,
            })
        }
        other => Err(PipeError::UnexpectedMessage(format!(
            "expected init as first message, got {other:?}"
        ))),
    }
}
