// SSH Packet基础结构定义
// 参考OpenSSH packet.c: ssh_packet_read(), ssh_packet_write()

use anyhow::{Result, anyhow};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Read, Write};

/// SSH Packet类型（参考OpenSSH SSH_MSG_*定义）
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PacketType {
    // SSH握手相关
    SSH_MSG_DISCONNECT = 1,
    SSH_MSG_IGNORE = 2,
    SSH_MSG_UNIMPLEMENTED = 3,
    SSH_MSG_DEBUG = 4,
    SSH_MSG_SERVICE_REQUEST = 5,
    SSH_MSG_SERVICE_ACCEPT = 6,
    SSH_MSG_KEXINIT = 20,
    SSH_MSG_NEWKEYS = 21,
    
    // 密钥交换相关
    SSH_MSG_KEXDH_INIT = 30,
    SSH_MSG_KEXDH_REPLY = 31,
    // 注意：Curve25519和DH使用相同的消息类型（30/31）
    // SSH_MSG_KEX_ECDH_INIT和SSH_MSG_KEX_ECDH_REPLY已在代码中注释
    // 使用SSH_MSG_KEXDH_INIT和SSH_MSG_KEXDH_REPLY代替
    
    // 认证相关
    SSH_MSG_USERAUTH_REQUEST = 50,
    SSH_MSG_USERAUTH_FAILURE = 51,
    SSH_MSG_USERAUTH_SUCCESS = 52,
    SSH_MSG_USERAUTH_BANNER = 53,
    SSH_MSG_USERAUTH_PK_OK = 60,
    
    // Channel相关
    SSH_MSG_GLOBAL_REQUEST = 80,
    SSH_MSG_REQUEST_SUCCESS = 81,
    SSH_MSG_REQUEST_FAILURE = 82,
    SSH_MSG_CHANNEL_OPEN = 90,
    SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91,
    SSH_MSG_CHANNEL_OPEN_FAILURE = 92,
    SSH_MSG_CHANNEL_WINDOW_ADJUST = 93,
    SSH_MSG_CHANNEL_DATA = 94,
    SSH_MSG_CHANNEL_EXTENDED_DATA = 95,
    SSH_MSG_CHANNEL_EOF = 96,
    SSH_MSG_CHANNEL_CLOSE = 97,
    SSH_MSG_CHANNEL_REQUEST = 98,
    SSH_MSG_CHANNEL_SUCCESS = 99,
    SSH_MSG_CHANNEL_FAILURE = 100,
}

/// SSH Packet结构（未加密状态）
/// 参考OpenSSH packet结构：
/// - packet_length (4 bytes)
/// - padding_length (1 byte)
/// - payload (variable)
/// - padding (variable)
/// - MAC (optional, encrypted阶段)
#[derive(Debug, Clone)]
pub struct SshPacket {
    pub packet_length: u32,
    pub padding_length: u8,
    pub payload: Vec<u8>,
    pub padding: Vec<u8>,
}

impl SshPacket {
    /// 创建新的SSH packet
    pub fn new(payload: Vec<u8>) -> Self {
        // 计算padding（SSH协议RFC 4253规范）
        // 参考OpenSSH packet.c: construct_packet()
        let block_size = 8;  // 未加密阶段block_size=8
        
        let payload_length = payload.len();
        let min_padding = 4;  // OpenSSH要求最少4字节padding
        
        // SSH协议约束：
        // packet_length = padding_length + payload_length + 1
        // (packet_length + 4) 必须是block_size的倍数
        // 
        // 计算：
        // (1 + payload_length + padding_length + 4) % 8 == 0
        // => (5 + payload_length + padding_length) % 8 == 0
        
        // 先尝试padding=4（最小）
        let mut padding_length = min_padding as u8;
        
        // 计算packet总长度（包括4字节的packet_length字段）
        let packet_length = 1 + payload_length + padding_length as usize;
        let total_length = packet_length + 4;  // 加上packet_length字段本身的4字节
        
        // 如果总长度不是block_size的倍数，增加padding
        if total_length % block_size != 0 {
            let remainder = total_length % block_size;
            padding_length += (block_size - remainder) as u8;
        }
        
        // 重新计算packet_length
        let packet_length = (1 + payload_length + padding_length as usize) as u32;
        
        // 生成随机padding（简化：使用0）
        let padding = vec![0u8; padding_length as usize];
        
        Self {
            packet_length,
            padding_length,
            payload,
            padding,
        }
    }
    
    /// 写入packet到stream（未加密阶段）
    /// 参考OpenSSH packet_write_poll()
    pub fn write<T: Write>(&self, stream: &mut T) -> Result<()> {
        // 写入packet_length（BigEndian）
        stream.write_u32::<BigEndian>(self.packet_length)?;
        
        // 写入padding_length
        stream.write_u8(self.padding_length)?;
        
        // 写入payload
        stream.write_all(&self.payload)?;
        
        // 写入padding
        stream.write_all(&self.padding)?;
        
        stream.flush()?;
        Ok(())
    }
    
    /// 从stream读取packet（未加密阶段）
    /// 参考OpenSSH packet_read_poll()
    pub fn read<T: Read>(stream: &mut T) -> Result<Self> {
        // 读取packet_length（BigEndian）
        let packet_length = stream.read_u32::<BigEndian>()?;
        
        // 检查packet长度限制（OpenSSH限制：256KB）
        if packet_length > 256 * 1024 {
            return Err(anyhow!("Packet too large: {}", packet_length));
        }
        
        // 读取padding_length
        let padding_length = stream.read_u8()?;
        
        // 读取payload（packet_length - padding_length - 1）
        let payload_length = packet_length - padding_length as u32 - 1;
        let mut payload = vec![0u8; payload_length as usize];
        stream.read_exact(&mut payload)?;
        
        // 读取padding
        let mut padding = vec![0u8; padding_length as usize];
        stream.read_exact(&mut padding)?;
        
        Ok(Self {
            packet_length,
            padding_length,
            payload,
            padding,
        })
    }
    
    /// 获取payload中的packet type
    pub fn get_type(&self) -> Result<PacketType> {
        if self.payload.is_empty() {
            return Err(anyhow!("Empty payload"));
        }
        
        let type_byte = self.payload[0];
        
        // 转换为PacketType enum
        match type_byte {
            1 => Ok(PacketType::SSH_MSG_DISCONNECT),
            2 => Ok(PacketType::SSH_MSG_IGNORE),
            3 => Ok(PacketType::SSH_MSG_UNIMPLEMENTED),
            4 => Ok(PacketType::SSH_MSG_DEBUG),
            5 => Ok(PacketType::SSH_MSG_SERVICE_REQUEST),
            6 => Ok(PacketType::SSH_MSG_SERVICE_ACCEPT),
            20 => Ok(PacketType::SSH_MSG_KEXINIT),
            21 => Ok(PacketType::SSH_MSG_NEWKEYS),
            30 => Ok(PacketType::SSH_MSG_KEXDH_INIT),
            31 => Ok(PacketType::SSH_MSG_KEXDH_REPLY),
            50 => Ok(PacketType::SSH_MSG_USERAUTH_REQUEST),
            51 => Ok(PacketType::SSH_MSG_USERAUTH_FAILURE),
            52 => Ok(PacketType::SSH_MSG_USERAUTH_SUCCESS),
            53 => Ok(PacketType::SSH_MSG_USERAUTH_BANNER),
            80 => Ok(PacketType::SSH_MSG_GLOBAL_REQUEST),
            81 => Ok(PacketType::SSH_MSG_REQUEST_SUCCESS),
            82 => Ok(PacketType::SSH_MSG_REQUEST_FAILURE),
            90 => Ok(PacketType::SSH_MSG_CHANNEL_OPEN),
            91 => Ok(PacketType::SSH_MSG_CHANNEL_OPEN_CONFIRMATION),
            92 => Ok(PacketType::SSH_MSG_CHANNEL_OPEN_FAILURE),
            93 => Ok(PacketType::SSH_MSG_CHANNEL_WINDOW_ADJUST),
            94 => Ok(PacketType::SSH_MSG_CHANNEL_DATA),
            95 => Ok(PacketType::SSH_MSG_CHANNEL_EXTENDED_DATA),
            96 => Ok(PacketType::SSH_MSG_CHANNEL_EOF),
            97 => Ok(PacketType::SSH_MSG_CHANNEL_CLOSE),
            98 => Ok(PacketType::SSH_MSG_CHANNEL_REQUEST),
            99 => Ok(PacketType::SSH_MSG_CHANNEL_SUCCESS),
            100 => Ok(PacketType::SSH_MSG_CHANNEL_FAILURE),
            _ => Err(anyhow!("Unknown packet type: {}", type_byte)),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    
    #[test]
    fn test_packet_creation() {
        let payload = vec![PacketType::SSH_MSG_KEXINIT as u8];
        let packet = SshPacket::new(payload);
        
        assert!(packet.packet_length > 0);
        assert!(packet.padding_length >= 4);
    }
    
    #[test]
    fn test_packet_write_read() {
        let payload = vec![PacketType::SSH_MSG_KEXINIT as u8];
        let packet = SshPacket::new(payload);
        
        let mut buffer = Vec::new();
        packet.write(&mut buffer).unwrap();
        
        let mut cursor = Cursor::new(buffer);
        let read_packet = SshPacket::read(&mut cursor).unwrap();
        
        assert_eq!(packet.packet_length, read_packet.packet_length);
        assert_eq!(packet.payload, read_packet.payload);
    }
}
