
// --- 1. 导入所需模块 ---
use thiserror::Error;
use zip::ZipArchive;
use std::fs::{self, File};
use std::io;
use std::path::PathBuf;
use serde::Serialize;
use tauri::Emitter;


// --- 2. (新增) 定义事件的有效负载 (Payload) ---
// 这个结构体将作为事件发送给 Svelte
#[derive(Clone, serde::Serialize)]
struct InstallProgress {
    message: String,
    percentage: f32, // 0.0 到 100.0
}

// --- 3. 错误定义 ---
#[derive(Debug, Error)]
pub enum InstallError {
    #[error("IO 错误: {0}")]
    Io(#[from] std::io::Error),

    #[error("Zip 解压错误: {0}")]
    Zip(#[from] zip::result::ZipError),

    #[error("找不到 data.bin 文件: {0}")]
    DataFileNotFound(String),


}


impl Serialize for InstallError {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(self.to_string().as_ref())
    }
}


#[tauri::command]
// --- 5. (修改) 添加 window 参数 ---
pub async fn install_game(window: tauri::Window, target_dir: String) -> Result<String, InstallError> {

    println!("Rust 后端收到命令：目标目录 {}", target_dir);

    // --- 6. 核心改动：从文件系统读取 data.bin ---

    // --- 6a. (新增) 发送启动事件 ---
    window.emit("install_progress", InstallProgress {
        message: "安装开始...".into(),
        percentage: 0.0
    }).ok();

    // 1. 获取 app.exe 所在的目录
    let exe_path = std::env::current_exe()?;
    let exe_dir = exe_path.parent()
        .ok_or_else(|| InstallError::Io(io::Error::new(io::ErrorKind::NotFound, "无法获取执行文件所在目录")))?;

    // 2. 构造 data.bin 的路径
    let data_bin_path = exe_dir.join("data.bin");

    println!("正在获取游戏资源包: {:?}", data_bin_path);
    window.emit("install_progress", InstallProgress {
        message: "正在获取游戏资源包".into(),
        percentage: 1.0 // 1%
    }).ok();


    if !data_bin_path.exists() {
        // 返回错误，Svelte 的 catch 块会捕获它
        return Err(InstallError::DataFileNotFound(
            format!("未在 {:?} 找到游戏资源包，请重新下载", data_bin_path)
        ));
    }

    // 3. 从硬盘打开文件
    let archive_file = File::open(&data_bin_path)?;
    println!("成功打开游戏资源包");
    window.emit("install_progress", InstallProgress {
        message: "成功打开游戏资源包".into(),
        percentage: 5.0 // 5%
    }).ok();


    // 4. ZipArchive 现在读取文件
    let mut archive = ZipArchive::new(archive_file)?;

    let total_files = archive.len() as f32;
    println!("在游戏资源包中找到 {} 个文件。", total_files);
    window.emit("install_progress", InstallProgress {
        message: format!("包中找到 {} 个文件。", total_files),
        percentage: 10.0 // 10%
    }).ok();


    // --- 7. 解压循环 (核心改动: 添加 emit) ---
    let install_path = PathBuf::from(target_dir);
    fs::create_dir_all(&install_path)?;

    for i in 0..archive.len() {
        let mut file = archive.by_index(i)?;

        let outpath = match file.enclosed_name() {
            Some(path) => install_path.join(path),
            None => continue,
        };

        // --- 7a. (核心) 计算百分比并发送事件 ---
        let current_file_index = i as f32;
        let percentage = 10.0 + (current_file_index / total_files) * 85.0; // (10% + 85% = 95%)
        let message = format!("安装中 [{}/{}]: {}", i + 1, total_files as u32, file.name());

        window.emit("install_progress", InstallProgress { message, percentage })
            .ok();

        // --- 2. (新增) 关键修复 ---
        // 释放线程 1 毫秒，给 Svelte 留出渲染时间
        // sleep(Duration::from_millis(1)).await;

        if (&*file.name()).ends_with('/') {
            fs::create_dir_all(&outpath)?;
        } else {
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    fs::create_dir_all(p)?;
                }
            }
            let mut outfile = File::create(&outpath)?;
            io::copy(&mut file, &mut outfile)?;
        }
    } // --- 循环结束 ---

    println!("Rust 后端：解压成功。");
    window.emit("install_progress", InstallProgress {
        message: "安装成功".into(),
        percentage: 100.0 // 100%
    }).ok();

    Ok(format!("成功解压 {} 个文件到指定目录！", total_files as u32))
}

