// SSH Channel协议实现（Phase 6）
// 参考OpenSSH channel.c

use crate::ssh_server::packet::{SshPacket, PacketType};
use std::io::{Read, Write};  // 导入Write trait（OpenSSH标准）
use anyhow::{Result, anyhow};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use log::{info, warn, debug};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

/// SSH Channel管理器（参考OpenSSH channel.c: struct channel）
pub struct ChannelManager {
    channels: HashMap<u32, Channel>,
    next_channel_id: u32,
}

impl ChannelManager {
    pub fn new() -> Self {
        Self {
            channels: HashMap::new(),
            next_channel_id: 0,
        }
    }
    
    /// 处理SSH_MSG_CHANNEL_OPEN（参考OpenSSH channel.c: channel_open())
    pub fn handle_channel_open(&mut self, packet: &SshPacket) -> Result<SshPacket> {
        info!("Processing SSH_MSG_CHANNEL_OPEN");
        
        let mut cursor = std::io::Cursor::new(packet.payload.as_slice());  // 使用as_slice()（Rust标准）
        
        // Packet type
        let packet_type = cursor.read_u8()?;
        if packet_type != PacketType::SSH_MSG_CHANNEL_OPEN as u8 {
            return Err(anyhow!("Invalid packet type for CHANNEL_OPEN"));
        }
        
        // 读取channel类型（SSH string）
        let channel_type = read_ssh_string(&mut cursor)?;
        
        // 读取sender channel ID（u32）
        let sender_channel = cursor.read_u32::<BigEndian>()?;
        
        // 读取初始窗口大小（u32）
        let initial_window_size = cursor.read_u32::<BigEndian>()?;
        
        // 读取最大packet大小（u32）
        let maximum_packet_size = cursor.read_u32::<BigEndian>()?;
        
        info!("Channel open: type={}, sender_channel={}, window={}, max_packet={}", 
              channel_type, sender_channel, initial_window_size, maximum_packet_size);
        
        // 检查channel类型（OpenSSH支持：session、x11、forwarded-tcpip、direct-tcpip）
        if channel_type != "session" {
            warn!("Unsupported channel type: {}", channel_type);
            return self.build_channel_open_failure(
                sender_channel,
                3,  // SSH_OPEN_UNKNOWN_CHANNEL_TYPE
                "Unsupported channel type",
                "en"
            );
        }
        
        // 创建新channel（参考OpenSSH channel.c）
        let server_channel = self.next_channel_id;
        self.next_channel_id += 1;
        
        let channel = Channel {
            server_channel,
            sender_channel,
            channel_type,
            window_size: initial_window_size,
            maximum_packet_size,
            state: ChannelState::Open,
        };
        
        self.channels.insert(server_channel, channel);
        
        info!("Channel created: server_channel={}, sender_channel={}", server_channel, sender_channel);
        
        // 构建SSH_MSG_CHANNEL_OPEN_CONFIRMATION（参考OpenSSH channel.c）
        self.build_channel_open_confirmation(server_channel, sender_channel, initial_window_size, maximum_packet_size)
    }
    
    /// 处理SSH_MSG_CHANNEL_REQUEST（参考OpenSSH channel.c: channel_request())
    pub fn handle_channel_request(&mut self, packet: &SshPacket) -> Result<Option<SshPacket>> {
        info!("Processing SSH_MSG_CHANNEL_REQUEST");
        
        let mut cursor = std::io::Cursor::new(packet.payload.as_slice());  // 使用as_slice()（Rust标准）
        
        // Packet type
        let packet_type = cursor.read_u8()?;
        if packet_type != PacketType::SSH_MSG_CHANNEL_REQUEST as u8 {
            return Err(anyhow!("Invalid packet type for CHANNEL_REQUEST"));
        }
        
        // 读取recipient channel（u32）
        let recipient_channel = cursor.read_u32::<BigEndian>()?;
        
        // 读取请求类型（SSH string）
        let request_type = read_ssh_string(&mut cursor)?;
        
        // 读取want reply标志（boolean）
        let want_reply = cursor.read_u8()? != 0;
        
        info!("Channel request: channel={}, type={}, want_reply={}", 
              recipient_channel, request_type, want_reply);
        
        // 处理不同请求类型（参考OpenSSH channel.c）
        if request_type == "exec" {
            self.handle_exec_request(&mut cursor, recipient_channel, want_reply)  // 移除?操作符（返回Option不是Result）
        } else if request_type == "subsystem" {
            self.handle_subsystem_request(&mut cursor, recipient_channel, want_reply)  // 移除?操作符
        } else if request_type == "shell" {
            self.handle_shell_request(recipient_channel, want_reply)  // 移除?操作符
        } else if request_type == "env" {
            self.handle_env_request(&mut cursor, recipient_channel, want_reply)  // 移除?操作符
        } else if request_type == "pty-req" {
            self.handle_pty_request(&mut cursor, recipient_channel, want_reply)  // 移除?操作符
        } else {
            warn!("Unsupported channel request: {}", request_type);
            if want_reply {
                Ok(Some(self.build_channel_failure(recipient_channel)?))
            } else {
                Ok(None)
            }
        }
    }
    
    /// 处理exec请求（参考OpenSSH channel.c: channel_request_exec())
    fn handle_exec_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result<Option<SshPacket>> {
        info!("Handling exec request for channel {}", channel);
        
        // 读取命令（SSH string）
        let command = read_ssh_string(cursor)?;
        
        info!("Exec command: {}", command);
        
        // 简化实现：返回成功（实际应执行命令）
        if want_reply {
            Ok(Some(self.build_channel_success(channel)?))
        } else {
            Ok(None)
        }
    }
    
    /// 处理subsystem请求（参考OpenSSH channel.c: channel_request_subsystem())
    fn handle_subsystem_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result<Option<SshPacket>> {
        info!("Handling subsystem request for channel {}", channel);
        
        // 读取subsystem名称（SSH string）
        let subsystem = read_ssh_string(cursor)?;
        
        info!("Subsystem: {}", subsystem);
        
        // 检查subsystem支持（OpenSSH支持：sftp）
        if subsystem == "sftp" {
            info!("SFTP subsystem requested");
            // Phase 7将实现SFTP
            if want_reply {
                Ok(Some(self.build_channel_success(channel)?))
            } else {
                Ok(None)
            }
        } else {
            warn!("Unsupported subsystem: {}", subsystem);
            if want_reply {
                Ok(Some(self.build_channel_failure(channel)?))
            } else {
                Ok(None)
            }
        }
    }
    
    /// 处理shell请求（参考OpenSSH channel.c）
    fn handle_shell_request(&mut self, channel: u32, want_reply: bool) -> Result<Option<SshPacket>> {
        info!("Handling shell request for channel {}", channel);
        
        // Phase 9将实现shell
        warn!("Shell not implemented in Phase 6");
        
        if want_reply {
            Ok(Some(self.build_channel_failure(channel)?))
        } else {
            Ok(None)
        }
    }
    
    /// 处理env请求（参考OpenSSH channel.c）
    fn handle_env_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result<Option<SshPacket>> {
        info!("Handling env request for channel {}", channel);
        
        // 读取环境变量名和值
        let name = read_ssh_string(cursor)?;
        let value = read_ssh_string(cursor)?;
        
        info!("Env: {}={}", name, value);
        
        if want_reply {
            Ok(Some(self.build_channel_success(channel)?))
        } else {
            Ok(None)
        }
    }
    
    /// 处理pty请求（参考OpenSSH channel.c）
    fn handle_pty_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result<Option<SshPacket>> {
        info!("Handling pty request for channel {}", channel);
        
        // 读取terminal类型
        let term = read_ssh_string(cursor)?;
        
        // 读取窗口大小
        let width = cursor.read_u32::<BigEndian>()?;
        let height = cursor.read_u32::<BigEndian>()?;
        let pixel_width = cursor.read_u32::<BigEndian>()?;
        let pixel_height = cursor.read_u32::<BigEndian>()?;
        
        // 读取terminal modes
        let modes_len = cursor.read_u32::<BigEndian>()?;
        let modes = read_ssh_string(cursor)?;
        
        info!("PTY: term={}, width={}, height={}", term, width, height);
        
        if want_reply {
            Ok(Some(self.build_channel_success(channel)?))
        } else {
            Ok(None)
        }
    }
    
    /// 处理SSH_MSG_CHANNEL_DATA（参考OpenSSH channel.c: channel_input_data())
    pub fn handle_channel_data(&mut self, packet: &SshPacket) -> Result<()> {
        info!("Processing SSH_MSG_CHANNEL_DATA");
        
        let mut cursor = std::io::Cursor::new(packet.payload.as_slice());  // 使用as_slice()（Rust标准）
        
        // Packet type
        let packet_type = cursor.read_u8()?;
        if packet_type != PacketType::SSH_MSG_CHANNEL_DATA as u8 {
            return Err(anyhow!("Invalid packet type for CHANNEL_DATA"));
        }
        
        // 读取recipient channel
        let recipient_channel = cursor.read_u32::<BigEndian>()?;
        
        // 读取数据（SSH string）
        let data = read_ssh_string(&mut cursor)?;
        
        info!("Channel data: channel={}, length={}", recipient_channel, data.len());
        
        // 简化实现：接受数据（实际应处理）
        
        Ok(())
    }
    
    /// 处理SSH_MSG_CHANNEL_CLOSE（参考OpenSSH channel.c: channel_input_close())
    pub fn handle_channel_close(&mut self, packet: &SshPacket) -> Result<Option<SshPacket>> {
        info!("Processing SSH_MSG_CHANNEL_CLOSE");
        
        let mut cursor = std::io::Cursor::new(packet.payload.as_slice());  // 使用as_slice()（Rust标准）
        
        // Packet type
        let packet_type = cursor.read_u8()?;
        if packet_type != PacketType::SSH_MSG_CHANNEL_CLOSE as u8 {
            return Err(anyhow!("Invalid packet type for CHANNEL_CLOSE"));
        }
        
        // 读取recipient channel
        let recipient_channel = cursor.read_u32::<BigEndian>()?;
        
        info!("Channel close: channel={}", recipient_channel);
        
        // 移除channel（参考OpenSSH channel.c）
        if let Some(channel) = self.channels.remove(&recipient_channel) {
            info!("Channel {} removed", recipient_channel);
            
            // 发送SSH_MSG_CHANNEL_CLOSE回应
            Ok(Some(self.build_channel_close(channel.sender_channel)?))
        } else {
            warn!("Channel {} not found", recipient_channel);
            Ok(None)
        }
    }
    
    /// 构建SSH_MSG_CHANNEL_OPEN_CONFIRMATION（参考OpenSSH channel.c）
    fn build_channel_open_confirmation(
        &self,
        server_channel: u32,
        sender_channel: u32,
        window_size: u32,
        packet_size: u32,
    ) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        // Packet type
        payload.write_u8(PacketType::SSH_MSG_CHANNEL_OPEN_CONFIRMATION as u8)?;
        
        // Server channel number
        payload.write_u32::<BigEndian>(server_channel)?;
        
        // Sender channel number
        payload.write_u32::<BigEndian>(sender_channel)?;
        
        // Initial window size
        payload.write_u32::<BigEndian>(window_size)?;
        
        // Maximum packet size
        payload.write_u32::<BigEndian>(packet_size)?;
        
        Ok(SshPacket::new(payload))
    }
    
    /// 构建SSH_MSG_CHANNEL_OPEN_FAILURE（参考OpenSSH channel.c）
    fn build_channel_open_failure(
        &self,
        sender_channel: u32,
        reason_code: u32,
        description: &str,
        language: &str,
    ) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        // Packet type
        payload.write_u8(PacketType::SSH_MSG_CHANNEL_OPEN_FAILURE as u8)?;
        
        // Sender channel number
        payload.write_u32::<BigEndian>(sender_channel)?;
        
        // Reason code
        payload.write_u32::<BigEndian>(reason_code)?;
        
        // Description（SSH string）
        payload.write_u32::<BigEndian>(description.len() as u32)?;
        payload.write_all(description.as_bytes())?;
        
        // Language（SSH string）
        payload.write_u32::<BigEndian>(language.len() as u32)?;
        payload.write_all(language.as_bytes())?;
        
        Ok(SshPacket::new(payload))
    }
    
    /// 构建SSH_MSG_CHANNEL_SUCCESS（参考OpenSSH channel.c）
    fn build_channel_success(&self, channel: u32) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        payload.write_u8(PacketType::SSH_MSG_CHANNEL_SUCCESS as u8)?;
        payload.write_u32::<BigEndian>(channel)?;
        
        Ok(SshPacket::new(payload))
    }
    
    /// 构建SSH_MSG_CHANNEL_FAILURE（参考OpenSSH channel.c）
    fn build_channel_failure(&self, channel: u32) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        payload.write_u8(PacketType::SSH_MSG_CHANNEL_FAILURE as u8)?;
        payload.write_u32::<BigEndian>(channel)?;
        
        Ok(SshPacket::new(payload))
    }
    
    /// 构建SSH_MSG_CHANNEL_CLOSE（参考OpenSSH channel.c）
    fn build_channel_close(&self, channel: u32) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        payload.write_u8(PacketType::SSH_MSG_CHANNEL_CLOSE as u8)?;
        payload.write_u32::<BigEndian>(channel)?;
        
        Ok(SshPacket::new(payload))
    }
}

/// SSH Channel结构（参考OpenSSH channel.c: struct channel）
struct Channel {
    server_channel: u32,
    sender_channel: u32,
    channel_type: String,
    window_size: u32,
    maximum_packet_size: u32,
    state: ChannelState,
}

/// SSH Channel状态（参考OpenSSH channel.c）
enum ChannelState {
    Open,
    Closing,
    Closed,
}

/// SSH string读取辅助函数
fn read_ssh_string<R: std::io::Read>(reader: &mut R) -> Result<String> {
    let length = reader.read_u32::<BigEndian>()?;
    let mut buffer = vec![0u8; length as usize];
    reader.read_exact(&mut buffer)?;
    Ok(String::from_utf8(buffer)?)
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_channel_manager_creation() {
        let manager = ChannelManager::new();
        assert_eq!(manager.next_channel_id, 0);
    }
    
    #[test]
    fn test_channel_open_confirmation() {
        let manager = ChannelManager::new();
        let packet = manager.build_channel_open_confirmation(0, 100, 2097152, 32768).unwrap();
        
        assert_eq!(packet.payload[0], PacketType::SSH_MSG_CHANNEL_OPEN_CONFIRMATION as u8);
    }
    
    #[test]
    fn test_channel_success() {
        let manager = ChannelManager::new();
        let packet = manager.build_channel_success(0).unwrap();
        
        assert_eq!(packet.payload[0], PacketType::SSH_MSG_CHANNEL_SUCCESS as u8);
    }
}
