// SSH认证协议实现（Phase 5）
// 参考OpenSSH auth.c, auth-passwd.c

use crate::ssh_server::packet::{SshPacket, PacketType};
use std::io::{Read, Write};  // 导入Write trait（OpenSSH标准）
// TODO: 使用新的SSH认证系统
// use crate::sftp::auth::SftpAuth;  // 已禁用旧的sftp模块
// use crate::sftp::config::SftpConfig;  // 已禁用旧的sftp模块
use anyhow::{Result, anyhow};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use log::{info, warn, debug};
use std::sync::Arc;

/// SSH认证处理器（参考OpenSSH auth2.c）
pub struct AuthHandler {
    // TODO: 使用新的SSH认证系统（替代旧的sftp模块）
    // config: Arc<SftpConfig>,  // 已禁用
    // auth_db: SftpAuth,  // 已禁用
    users: std::collections::HashMap<String, String>,  // 临时：用户名→密码hash
}

impl AuthHandler {
    /// 创建认证处理器
    pub fn new() -> Result<Self> {
        // TODO: 使用新的SSH认证系统
        // let auth_db = SftpAuth::new(&config.auth_db_path)?;
        
        // 临时：使用HashMap存储用户
        let users = std::collections::HashMap::new();
        
        Ok(Self { users })
    }
    
    /// 处理SSH_MSG_USERAUTH_REQUEST（参考OpenSSH auth2.c: userauth_request()）
    pub fn handle_userauth_request(&mut self, packet: &SshPacket) -> Result<AuthResult> {
        info!("Processing SSH_MSG_USERAUTH_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_USERAUTH_REQUEST as u8 {
            return Err(anyhow!("Invalid packet type for USERAUTH_REQUEST"));
        }
        
        // 读取用户名（SSH string）
        let user = read_ssh_string(&mut cursor)?;
        
        // 读取服务名称（SSH string）
        let service = read_ssh_string(&mut cursor)?;
        
        // 读取认证方法名称（SSH string）
        let method = read_ssh_string(&mut cursor)?;
        
        info!("Auth request: user={}, service={}, method={}", user, service, method);
        
        // 检查服务名称（OpenSSH要求：ssh-connection）
        if service != "ssh-connection" {
            warn!("Unsupported service: {}", service);
            return Ok(AuthResult::Failure("Unsupported service".to_string()));
        }
        
        // 根据认证方法处理（参考OpenSSH auth2.c）
        if method == "password" {
            self.handle_password_auth(&mut cursor, &user)  // 移除?操作符（返回AuthResult不是Result）
        } else if method == "publickey" {
            // Phase 5仅实现password认证，publickey留待Phase 9优化
            warn!("Public key auth not implemented in Phase 5");
            Ok(AuthResult::Failure("Public key auth not implemented".to_string()))
        } else if method == "none" {
            // OpenSSH：none认证总是失败（用于查询支持的认证方法）
            warn!("None auth request");
            Ok(AuthResult::Failure("Authentication required".to_string()))
        } else {
            warn!("Unsupported auth method: {}", method);
            Ok(AuthResult::Failure("Unsupported auth method".to_string()))
        }
    }
    
    /// 处理password认证（参考OpenSSH auth-passwd.c）
    fn handle_password_auth(&mut self, cursor: &mut std::io::Cursor<&[u8]>, user: &str) -> Result<AuthResult> {
        info!("Handling password auth for user: {}", user);
        
        // 读取是否修改密码标志（boolean，OpenSSH password认证格式）
        let change_password = cursor.read_u8()? != 0;
        
        if change_password {
            warn!("Password change not supported");
            return Ok(AuthResult::Failure("Password change not supported".to_string()));
        }
        
        // 读取密码（SSH string）
        let password = read_ssh_string(cursor)?;
        
        debug!("Password auth attempt: user={}, password length={}", user, password.len());
        
        // 使用bcrypt验证（复用sftp/auth.rs）
// 使用users字段临时验证（OpenSSH标准）
        if let Some(stored_password) = self.users.get(user) {
            // TODO: 使用bcrypt验证
            if stored_password == &password {
                info!("Password auth successful for user: {}", user);
                return Ok(AuthResult::Success);
            }
        }
        
        warn!("Password auth failed for user: {}", user);
        Ok(AuthResult::Failure("Invalid password".to_string()))
    }
    
    /// 构建SSH_MSG_USERAUTH_SUCCESS packet（参考OpenSSH auth2.c）
    pub fn build_userauth_success() -> Result<SshPacket> {
        let payload = vec![PacketType::SSH_MSG_USERAUTH_SUCCESS as u8];
        Ok(SshPacket::new(payload))
    }
    
    /// 构建SSH_MSG_USERAUTH_FAILURE packet（参考OpenSSH auth2.c）
    pub fn build_userauth_failure(methods: &[String], partial_success: bool) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        // Packet type
        payload.write_u8(PacketType::SSH_MSG_USERAUTH_FAILURE as u8)?;
        
        // 认证方法列表（SSH string，逗号分隔）
        let methods_str = methods.join(",");
        payload.write_u32::<BigEndian>(methods_str.len() as u32)?;
        payload.write_all(methods_str.as_bytes())?;
        
        // partial_success标志（boolean）
        payload.write_u8(if partial_success { 1 } else { 0 })?;
        
        Ok(SshPacket::new(payload))
    }
    
    /// 构建SSH_MSG_USERAUTH_BANNER packet（可选，参考OpenSSH auth2.c）
    pub fn build_userauth_banner(message: &str, language: &str) -> Result<SshPacket> {
        let mut payload = Vec::new();
        
        // Packet type
        payload.write_u8(PacketType::SSH_MSG_USERAUTH_BANNER as u8)?;
        
        // Banner message（SSH string）
        payload.write_u32::<BigEndian>(message.len() as u32)?;
        payload.write_all(message.as_bytes())?;
        
        // Language tag（SSH string）
        payload.write_u32::<BigEndian>(language.len() as u32)?;
        payload.write_all(language.as_bytes())?;
        
        Ok(SshPacket::new(payload))
    }
}

/// SSH认证结果（参考OpenSSH auth2.c）
pub enum AuthResult {
    Success,
    Failure(String),  // 失败原因
    PartialSuccess,   // 部分成功（多步骤认证）
}

/// 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_userauth_success_packet() {
        let packet = AuthHandler::build_userauth_success().unwrap();
        assert_eq!(packet.payload[0], PacketType::SSH_MSG_USERAUTH_SUCCESS as u8);
    }
    
    #[test]
    fn test_userauth_failure_packet() {
        let methods = vec!["password".to_string(), "publickey".to_string()];
        let packet = AuthHandler::build_userauth_failure(&methods, false).unwrap();
        
        assert_eq!(packet.payload[0], PacketType::SSH_MSG_USERAUTH_FAILURE as u8);
    }
}
