//! 通用文件 IO 命令
//!
//! 安全模型：capability 保留 broad scope（"/\**"），实际访问控制下沉到 Rust Command 层。
//! 前端禁止直接调用 plugin-fs readFile / convertFileSrc，所有文件访问必须走本模块的 Command。

use std::path::Path;
use crate::ApiResponse;

// ============================================================
// 路径安全检查
// ============================================================

/// 拒绝路径遍历
fn check_traversal(path: &str) -> Result<(), String> {
    if path.contains("..") {
        return Err("非法路径：包含目录遍历组件".into());
    }
    Ok(())
}

/// 要求绝对路径（拒绝相对路径，消除工作目录歧义）
fn check_absolute(path: &Path) -> Result<(), String> {
    if !path.is_absolute() {
        return Err("非法路径：必须是绝对路径".into());
    }
    Ok(())
}

/// 拒绝已知的系统敏感目录（macOS / Linux / Windows）
fn check_sensitive_path(path: &Path) -> Result<(), String> {
    let path_str = path.to_string_lossy().to_lowercase();

    // macOS / Linux 系统目录
    let unix_denied = [
        "/etc/", "/bin/", "/sbin/", "/usr/bin/", "/usr/sbin/",
        "/lib/", "/lib64/", "/system/", "/sys/", "/dev/",
        "/private/etc/", "/private/var/db/",
    ];
    for prefix in &unix_denied {
        if path_str.starts_with(prefix) {
            return Err(format!("非法路径：系统敏感目录 {}", prefix));
        }
    }

    // Windows 系统目录
    let win_denied = [
        r"c:\windows\", r"c:\program files\", r"c:\program files (x86)\",
        r"c:\programdata\", r"c:\users\all users\",
    ];
    for prefix in &win_denied {
        if path_str.starts_with(prefix) {
            return Err(format!("非法路径：系统敏感目录 {}", prefix));
        }
    }

    Ok(())
}

/// 综合路径安全校验
///
/// 返回校验通过后的 Path 引用，失败时返回 400 响应。
fn validate_path(path: &str) -> Result<&Path, ApiResponse<()>> {
    if let Err(e) = check_traversal(path) {
        return Err(ApiResponse { code: 400, message: e, data: None });
    }

    let p = Path::new(path);

    if let Err(e) = check_absolute(p) {
        return Err(ApiResponse { code: 400, message: e, data: None });
    }

    if let Err(e) = check_sensitive_path(p) {
        return Err(ApiResponse { code: 403, message: e, data: None });
    }

    Ok(p)
}

/// 通用文件元数据校验（是否为文件、是否可读等）
fn validate_file_meta(path: &Path) -> Result<std::fs::Metadata, ApiResponse<()>> {
    match std::fs::metadata(path) {
        Ok(meta) if meta.is_file() => Ok(meta),
        Ok(_) => Err(ApiResponse {
            code: 400,
            message: "指定路径不是文件".into(),
            data: None,
        }),
        Err(e) => Err(ApiResponse {
            code: 500,
            message: format!("无法访问文件: {}", e),
            data: None,
        }),
    }
}

// ============================================================
// Command 接口
// ============================================================

/// 校验媒体文件路径安全性
///
/// 返回校验结果（不读取内容），供前端在调用 convertFileSrc 前做安全门岗。
/// 校验通过时返回原始路径；失败时返回 400/403。
#[tauri::command]
pub async fn validate_media_path(path: String) -> ApiResponse<String> {
    // 复用同样的路径安全策略
    let file_path = match validate_path(&path) {
        Ok(p) => p,
        Err(resp) => {
            return ApiResponse {
                code: resp.code,
                message: resp.message,
                data: None,
            };
        }
    };

    match validate_file_meta(file_path) {
        Ok(meta) => ApiResponse {
            code: 200,
            message: format!("校验通过，文件大小 {} 字节", meta.len()),
            data: Some(path),
        },
        Err(resp) => ApiResponse {
            code: resp.code,
            message: resp.message,
            data: None,
        },
    }
}
