//! 项目存储命令

use crate::ApiResponse;
use crate::StringResultExt;
use crate::storage::project as project_storage;

// ============================================================
// 命令函数
// ============================================================

#[tauri::command]
pub async fn save_project_meta_raw(project_id: String, json_content: String) -> ApiResponse<bool> {
    match project_storage::save_project_meta_raw(&project_id, &json_content).map_err_string() {
        Ok(_) => ApiResponse {
            code: 200,
            message: "Project saved successfully".to_string(),
            data: Some(true),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to save project: {}", e),
            data: None,
        },
    }
}

#[tauri::command]
pub async fn load_project_meta(project_id: String) -> ApiResponse<serde_json::Value> {
    match project_storage::load_project_meta(&project_id).map_err_string() {
        Ok(data) => ApiResponse {
            code: 200,
            message: "Project loaded successfully".to_string(),
            data: Some(data),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to load project: {}", e),
            data: None,
        },
    }
}

#[tauri::command]
pub async fn save_project_segments_raw(project_id: String, json_content: String) -> ApiResponse<bool> {
    match project_storage::save_project_segments_raw(&project_id, &json_content).map_err_string() {
        Ok(_) => ApiResponse {
            code: 200,
            message: "Segments saved successfully".to_string(),
            data: Some(true),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to save segments: {}", e),
            data: None,
        },
    }
}

#[tauri::command]
pub async fn load_project_segments(project_id: String) -> ApiResponse<serde_json::Value> {
    match project_storage::load_project_segments(&project_id).map_err_string() {
        Ok(data) => ApiResponse {
            code: 200,
            message: "Segments loaded successfully".to_string(),
            data: Some(data),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to load segments: {}", e),
            data: None,
        },
    }
}

#[tauri::command]
pub async fn list_local_projects() -> ApiResponse<Vec<serde_json::Value>> {
    match project_storage::list_projects().map_err_string() {
        Ok(projects) => ApiResponse {
            code: 200,
            message: "Projects listed successfully".to_string(),
            data: Some(projects),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to list projects: {}", e),
            data: Some(vec![]),
        },
    }
}

#[tauri::command]
pub async fn delete_local_project(project_id: String) -> ApiResponse<bool> {
    match project_storage::delete_project(&project_id).map_err_string() {
        Ok(_) => ApiResponse {
            code: 200,
            message: "Project deleted successfully".to_string(),
            data: Some(true),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to delete project: {}", e),
            data: None,
        },
    }
}

#[tauri::command]
pub async fn delete_project_file(project_id: String, file_path: String) -> ApiResponse<bool> {
    use crate::storage::get_project_dir_path;

    let project_dir: std::path::PathBuf = match get_project_dir_path(&project_id) {
        Ok(d) => d,
        Err(e) => return ApiResponse {
            code: 500,
            message: format!("{}", e),
            data: None,
        },
    };

    // 支持绝对路径（前端 get_video_save_path 返回的）和相对路径
    let target = std::path::PathBuf::from(&file_path);

    // 安全检查：确保文件在项目目录内（canonicalize 后比较）
    let canonical_target = match target.canonicalize() {
        Ok(p) => p,
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
            return ApiResponse {
                code: 200,
                message: "File not found, nothing to delete".to_string(),
                data: Some(true),
            };
        }
        Err(e) => return ApiResponse {
            code: 500,
            message: format!("Failed to resolve path: {}", e),
            data: None,
        },
    };

    let canonical_project = match project_dir.canonicalize() {
        Ok(p) => p,
        Err(e) => return ApiResponse {
            code: 500,
            message: format!("Failed to resolve project dir: {}", e),
            data: None,
        },
    };

    if !canonical_target.starts_with(&canonical_project) {
        return ApiResponse {
            code: 400,
            message: "Path traversal detected".to_string(),
            data: None,
        };
    }

    match std::fs::remove_file(&target) {
        Ok(_) => ApiResponse {
            code: 200,
            message: "File deleted".to_string(),
            data: Some(true),
        },
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => ApiResponse {
            code: 200,
            message: "File not found, nothing to delete".to_string(),
            data: Some(true),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to delete file: {}", e),
            data: None,
        },
    }
}

