//! HTTP 文件传输客户端
//! 用于向其他设备上传/下载文件

use std::path::PathBuf;
use std::sync::Arc;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tauri::{AppHandle, Emitter};
use tokio_util::sync::CancellationToken;

use crate::models::{DeviceInfo, TransferProgressEvent, TransferStatus};
use crate::utils::{AppError, FILE_CHUNK_SIZE};
use crate::models::event_names;

/// HTTP 传输客户端
#[derive(Clone)]
pub struct HttpClient {
    /// Tauri AppHandle (可选，用于发送事件)
    app_handle: Arc<std::sync::RwLock<Option<AppHandle>>>,
}

impl HttpClient {
    /// 创建新的客户端
    pub fn new() -> Self {
        Self { 
            app_handle: Arc::new(std::sync::RwLock::new(None)),
        }
    }

    /// 设置 AppHandle
    pub fn set_app_handle(&self, handle: AppHandle) {
        if let Ok(mut guard) = self.app_handle.write() {
            *guard = Some(handle);
        }
    }

    /// 上传文件到指定设备（支持取消）
    pub async fn upload_file(
        &self,
        device: &DeviceInfo,
        file_path: &PathBuf,
        file_id: &str,
        from_device: &str,
        cancel_token: CancellationToken,
    ) -> Result<(), AppError> {
        use tokio::net::TcpStream;
        use tokio::io::{AsyncBufReadExt, BufReader};
        
        let file_name = file_path
            .file_name()
            .map(|s| s.to_string_lossy().to_string())
            .unwrap_or_else(|| "unknown".to_string());
        
        let addr = format!("{}:{}", device.ip, device.http_port);
        let stream = TcpStream::connect(&addr).await?;
        
        // TLS 握手
        let connector = crate::tls::client::build_connector()?;
        let ip_addr: std::net::IpAddr = device.ip.parse()
            .map_err(|_| AppError::Tls("Invalid IP address".to_string()))?;
        let server_name = rustls::ServerName::IpAddress(ip_addr);
        
        let mut tls_stream = connector.connect(server_name, stream).await
            .map_err(|e| AppError::Tls(format!("TLS error: {}", e)))?;
        
        // 读取文件内容
        let mut file = File::open(file_path).await?;
        let file_size = file.metadata().await?.len();
        let mut file_content = Vec::with_capacity(file_size as usize);
        file.read_to_end(&mut file_content).await?;
        
        // 构建 multipart 请求体
        let boundary = format!("----WebKitFormBoundary{}", uuid::Uuid::new_v4().to_string().replace("-", "")[..16].to_string());
        
        let mut body = Vec::new();
        body.extend_from_slice(format!("--{}\r\n", boundary).as_bytes());
        body.extend_from_slice(format!("Content-Disposition: form-data; name=\"file_id\"\r\n\r\n{}\r\n", file_id).as_bytes());
        body.extend_from_slice(format!("--{}\r\n", boundary).as_bytes());
        body.extend_from_slice(format!("Content-Disposition: form-data; name=\"from_device\"\r\n\r\n{}\r\n", from_device).as_bytes());
        body.extend_from_slice(format!("--{}\r\n", boundary).as_bytes());
        body.extend_from_slice(format!("Content-Disposition: form-data; name=\"file\"; filename=\"{}\"\r\n", file_name).as_bytes());
        body.extend_from_slice(b"Content-Type: application/octet-stream\r\n\r\n");
        body.extend_from_slice(&file_content);
        body.extend_from_slice(format!("\r\n--{}--\r\n", boundary).as_bytes());
        
        let request = format!(
            "POST /upload HTTP/1.1\r\n\
             Host: {}\r\n\
             Content-Type: multipart/form-data; boundary={}\r\n\
             Content-Length: {}\r\n\
             Connection: close\r\n\
             \r\n",
            addr,
            boundary,
            body.len()
        );
        
        tls_stream.write_all(request.as_bytes()).await?;
        
        // 分块发送请求体，同时检查取消状态
        let mut sent = 0usize;
        for chunk in body.chunks(FILE_CHUNK_SIZE) {
            // 检查是否已取消
            if cancel_token.is_cancelled() {
                self.emit_progress(file_id, 0.0, sent as u64, file_size, TransferStatus::Cancelled);
                if let Err(e) = crate::database::Database::update_transfer_progress(file_id, 0.0, sent as u64, "cancelled") {
                    log::error!("Failed to update transfer in database: {}", e);
                }
                log::info!("File upload cancelled: {}", file_name);
                return Err(AppError::FileTransfer("Upload cancelled".to_string()));
            }
            
            tls_stream.write_all(chunk).await?;
            sent += chunk.len();
            
            let progress = sent as f64 / body.len() as f64;
            self.emit_progress(file_id, progress, sent as u64, file_size, TransferStatus::Transferring);
        }
        
        tls_stream.flush().await?;
        
        // 读取响应
        let mut reader = BufReader::new(tls_stream);
        let mut response_line = String::new();
        reader.read_line(&mut response_line).await?;
        
        if response_line.contains("200") {
            self.emit_progress(file_id, 1.0, file_size, file_size, TransferStatus::Completed);
            if let Err(e) = crate::database::Database::update_transfer_progress(file_id, 1.0, file_size, "completed") {
                log::error!("Failed to update transfer in database: {}", e);
            }
            log::info!("File uploaded successfully: {}", file_name);
            Ok(())
        } else {
            self.emit_progress(file_id, 0.0, 0, file_size, TransferStatus::Failed);
            if let Err(e) = crate::database::Database::update_transfer_progress(file_id, 0.0, 0, "failed") {
                log::error!("Failed to update transfer in database: {}", e);
            }
            Err(AppError::FileTransfer(format!("Upload failed: {}", response_line)))
        }
    }

    /// 发送进度事件
    fn emit_progress(&self, file_id: &str, progress: f64, transferred: u64, total: u64, status: TransferStatus) {
        let event = TransferProgressEvent {
            file_id: file_id.to_string(),
            progress,
            transferred_bytes: transferred,
            total_bytes: total,
            status,
            file_name: None,  // 发送方不需要文件名
            local_path: None, // 发送方不需要本地路径
        };
        
        // 直接通过 AppHandle 发送事件
        if let Ok(guard) = self.app_handle.read() {
            if let Some(ref handle) = *guard {
                let _ = handle.emit(event_names::TRANSFER_PROGRESS, &event);
            }
        }
    }
}

impl Default for HttpClient {
    fn default() -> Self {
        Self::new()
    }
}
