//! Voice 音频管理 IPC 命令

use crate::ApiResponse;
use crate::storage::voice as voice_storage;

// --------------------- 音色素材库命令 ---------------------

#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VoiceMaterialArgs {
    pub id: String,
    pub name: String,
    pub voice_id: String,
    pub source_url: String,
    pub trial_url: Option<String>,
    pub status: String,
    pub created_at: String,
}

/// 加载音色素材库
#[tauri::command]
pub async fn load_voice_materials() -> ApiResponse<Vec<voice_storage::VoiceMaterial>> {
    match voice_storage::load_voice_materials() {
        Ok(list) => ApiResponse {
            code: 200,
            message: "素材库加载成功".to_string(),
            data: Some(list.materials),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("加载素材库失败: {}", e),
            data: Some(vec![]),
        },
    }
}

/// 保存音色素材
#[tauri::command]
pub async fn save_voice_material(
    args: VoiceMaterialArgs,
) -> ApiResponse<bool> {
    let material = voice_storage::VoiceMaterial {
        id: args.id,
        name: args.name,
        voice_id: args.voice_id,
        source_url: args.source_url,
        trial_url: args.trial_url,
        status: args.status,
        created_at: args.created_at,
    };
    match voice_storage::add_voice_material(material) {
        Ok(_) => ApiResponse {
            code: 200,
            message: "素材保存成功".to_string(),
            data: Some(true),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("保存素材失败: {}", e),
            data: Some(false),
        },
    }
}

/// 删除音色素材
#[tauri::command]
pub async fn delete_voice_material_cmd(
    id: String,
) -> ApiResponse<bool> {
    match voice_storage::delete_voice_material(&id) {
        Ok(_) => ApiResponse {
            code: 200,
            message: "素材删除成功".to_string(),
            data: Some(true),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("删除素材失败: {}", e),
            data: Some(false),
        },
    }
}

// --------------------- 音频文件命令 ---------------------

#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SaveAudioArgs {
    pub project_id: String,
    pub audio_id: String,
    pub audio_data: String,
    pub name: String,
    pub voice_id: String,
    pub duration: f64,
}

/// 保存音频文件（前端传入 base64 编码）
#[tauri::command]
pub async fn save_audio(
    args: SaveAudioArgs,
) -> ApiResponse<voice_storage::AudioMeta> {
    let audio_bytes = match base64::Engine::decode(
        &base64::engine::general_purpose::STANDARD,
        &args.audio_data,
    ) {
        Ok(data) => data,
        Err(e) => return ApiResponse {
            code: 400,
            message: format!("Invalid base64 data: {}", e),
            data: None,
        },
    };

    match voice_storage::save_audio_file(
        &args.project_id,
        &args.audio_id,
        &audio_bytes,
        &args.name,
        &args.voice_id,
        args.duration,
    ) {
        Ok(meta) => ApiResponse {
            code: 200,
            message: "Audio saved successfully".to_string(),
            data: Some(meta),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to save audio: {}", e),
            data: None,
        },
    }
}

// --------------------- 音频截取与上传 ---------------------

#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ExtractAudioSegmentArgs {
    pub input_path: String,
    pub start: f64,
    pub duration: f64,
    pub output_path: String,
}

/// 截取音频片段（FFmpeg）
#[tauri::command]
pub async fn extract_audio_segment(
    app: tauri::AppHandle,
    args: ExtractAudioSegmentArgs,
) -> ApiResponse<String> {
    match crate::ffmpeg_cmd::extract_audio_segment(
        &app,
        &args.input_path,
        args.start,
        args.duration,
        &args.output_path,
    ).await {
        Ok(_) => ApiResponse {
            code: 200,
            message: "Audio segment extracted successfully".to_string(),
            data: Some(args.output_path),
        },
        Err(e) => ApiResponse {
            code: 500,
            message: format!("Failed to extract audio segment: {}", e),
            data: None,
        },
    }
}

/// 上传本地音频文件到后端，后端上传到七牛云并返回 URL
#[tauri::command]
pub async fn upload_audio_file(
    app: tauri::AppHandle,
    local_path: String,
) -> ApiResponse<crate::commands::video_compose::UploadVideoResult> {
    // 验证路径安全
    let safe_path = match crate::ffmpeg_cmd::sanitize_output_path(&local_path) {
        Ok(p) => p,
        Err(e) => {
            return ApiResponse {
                code: 500,
                message: format!("路径验证失败: {}", e),
                data: None,
            };
        }
    };

    crate::commands::video_compose::upload_file_to_backend(
        &app,
        &safe_path,
        "/upload/audio",
        "audio.mp3",
        "audio/mpeg",
        "读取音频文件失败",
    ).await
}
