//! 项目数据存储
//!
//! 负责项目元数据（meta.json）和分镜数据（segments.json）的读写。
//! 所有操作通过 StorageEngine 的路径净化 + 原子写入 + 文件锁。

use std::fs;
use std::path::PathBuf;
use serde_json::Value;
use base64::Engine as _;
use crate::storage::engine::{
    atomic_write_json, atomic_write_bytes, with_file_lock, read_json,
    sanitize_filename, StorageError,
};
use crate::storage::paths::{
    get_project_dir, get_project_dir_path, get_project_assets_dir, get_project_videos_dir,
};

// ============================================================
// 元数据读写
// ============================================================

/// 保存项目元数据
pub fn save_project_meta(
    project_id: &str,
    data: &Value,
) -> Result<(), StorageError> {
    let dir = get_project_dir(project_id)?;
    let path = dir.join("meta.json");
    with_file_lock(&path, || {
        atomic_write_json(&path, data)
    })
}

/// 保存项目元数据（原始 JSON 字符串）
pub fn save_project_meta_raw(
    project_id: &str,
    json_content: &str,
) -> Result<(), StorageError> {
    let data: Value = serde_json::from_str(json_content)?;
    save_project_meta(project_id, &data)
}

/// 加载项目元数据
pub fn load_project_meta(
    project_id: &str,
) -> Result<Value, StorageError> {
    let dir = get_project_dir_path(project_id)?;
    let path = dir.join("meta.json");
    match read_json(&path)? {
        Some(data) => Ok(data),
        None => Ok(Value::Null),
    }
}

// ============================================================
// 分镜数据读写
// ============================================================

/// 保存分镜数据
pub fn save_project_segments(
    project_id: &str,
    segments: &Value,
) -> Result<(), StorageError> {
    let dir = get_project_dir(project_id)?;
    let path = dir.join("segments.json");
    with_file_lock(&path, || {
        atomic_write_json(&path, segments)
    })
}

/// 保存分镜数据（原始 JSON 字符串）
pub fn save_project_segments_raw(
    project_id: &str,
    json_content: &str,
) -> Result<(), StorageError> {
    let data: Value = serde_json::from_str(json_content)?;
    save_project_segments(project_id, &data)
}

/// 加载分镜数据
pub fn load_project_segments(
    project_id: &str,
) -> Result<Value, StorageError> {
    let dir = get_project_dir_path(project_id)?;
    let path = dir.join("segments.json");
    match read_json(&path)? {
        Some(data) => Ok(data),
        None => Ok(Value::Array(vec![])),
    }
}

// ============================================================
// 项目列表
// ============================================================

/// 列出所有本地项目
///
/// 遍历 projects 目录，读取每个项目的 meta.json。
/// 读取失败的项目会被跳过并记录警告，不会导致整个列表失败。
pub fn list_projects() -> Result<Vec<Value>, StorageError> {
    let base = get_meijiaka_dir()?;
    let projects_dir = base.join("projects");

    if !projects_dir.exists() {
        return Ok(vec![]);
    }

    let mut projects = Vec::new();
    for entry in fs::read_dir(&projects_dir)? {
        let entry = match entry {
            Ok(e) => e,
            Err(e) => {
                eprintln!("[storage] Failed to read directory entry: {}", e);
                continue;
            }
        };

        let path = entry.path();
        if !path.is_dir() {
            continue;
        }

        let meta_path = path.join("meta.json");
        match read_json::<Value>(&meta_path) {
            Ok(Some(meta)) => projects.push(meta),
            Ok(None) => {
                eprintln!("[storage] meta.json not found for project: {:?}", path);
            }
            Err(e) => {
                eprintln!("[storage] Failed to parse meta.json for {:?}: {}", path, e);
            }
        }
    }

    Ok(projects)
}

// ============================================================
// 删除项目
// ============================================================

/// 删除本地项目
///
/// 使用 `get_project_dir_path`（不自动创建目录），
/// 避免删除不存在项目时先创建空目录的 bug。
pub fn delete_project(project_id: &str) -> Result<(), StorageError> {
    let dir = get_project_dir_path(project_id)?;
    if dir.exists() {
        fs::remove_dir_all(&dir)?;
    }
    Ok(())
}

// ============================================================
// 资源文件
// ============================================================

/// 保存项目资源（Base64 解码后写入）
pub fn save_project_asset(
    project_id: &str,
    filename: &str,
    base64_data: &str,
) -> Result<String, StorageError> {
    let safe_filename = sanitize_filename(filename)?;
    let dir = get_project_assets_dir(project_id)?;
    let path = dir.join(&safe_filename);

    let decoded = base64::engine::general_purpose::STANDARD
        .decode(base64_data)
        .map_err(|e| StorageError::InvalidId(format!("base64 decode failed: {}", e)))?;

    atomic_write_bytes(&path, &decoded)?;

    Ok(path.to_string_lossy().to_string())
}

/// 获取视频保存路径（不写入文件）
/// 保存到项目 videos 目录下，与后端下载路径保持一致
pub fn get_video_save_path(
    project_id: &str,
    filename: &str,
) -> Result<PathBuf, StorageError> {
    let safe_filename = sanitize_filename(filename)?;
    let dir = get_project_videos_dir(project_id)?;
    Ok(dir.join(&safe_filename))
}

// 兼容旧接口：从 persistence.rs 迁移时需要的 get_meijiaka_dir
fn get_meijiaka_dir() -> Result<std::path::PathBuf, StorageError> {
    crate::storage::paths::get_app_data_dir()
        .map(|p| p.to_path_buf())
}
