use anyhow::{anyhow, Result};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tracing::{error, info, warn};
use uuid::Uuid;
use chrono::{DateTime, Utc};
use hmac::{Hmac, Mac};
use sha2::{Digest, Sha256};
use hex;
use url::Url;

use crate::data::models::video_generation_record::{
    VideoGenerationRecord, CreateVideoGenerationRequest, VideoGenerationQuery
};
use crate::data::repositories::video_generation_record_repository::VideoGenerationRecordRepository;
use crate::infrastructure::database::Database;
use crate::business::services::cloud_upload_service::CloudUploadService;

/// 火山云视频生成API响应（提交任务）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolcanoVideoGenerationResponse {
    pub code: i32,
    pub message: String,
    pub data: Option<VolcanoVideoGenerationData>,
    pub request_id: String,
    pub status: i32,
    pub time_elapsed: String,
}

/// 提交任务返回数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolcanoVideoGenerationData {
    pub task_id: String,
}

/// 火山云查询任务API响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolcanoVideoQueryResponse {
    pub code: i32,
    pub message: String,
    pub data: Option<VolcanoVideoQueryData>,
    pub request_id: String,
    pub status: i32,
    pub time_elapsed: String,
}

/// 查询任务返回数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolcanoVideoQueryData {
    pub status: String, // in_queue, generating, done, not_found, expired
    pub video_url: Option<String>,
    pub resp_data: Option<String>, // JSON字符串，包含详细信息
}

/// 驱动视频信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DrivingVideoInfo {
    /// 驱动视频存储类型，传固定值0
    pub store_type: i32,
    /// 视频url
    pub video_url: String,
}

/// 火山云视频生成请求参数（提交任务）
/// 基于火山云实际API文档的参数
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolcanoVideoGenerationRequest {
    /// 服务标识，固定值
    pub req_key: String,
    /// 输入图片URL（必需）
    pub image_url: String,
    /// 驱动视频信息
    pub driving_video_info: DrivingVideoInfo,
}

/// 火山云查询任务请求参数
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolcanoVideoQueryRequest {
    /// 服务标识，固定值
    pub req_key: String,
    /// 任务ID
    pub task_id: String,
}

/// 火山云视频生成服务
/// 遵循 Tauri 开发规范的服务层设计原则
pub struct VolcanoVideoService {
    database: Arc<Database>,
    repository: VideoGenerationRecordRepository,
    http_client: Client,
    cloud_upload_service: CloudUploadService,
    vol_access_key: String,
    vol_secret_key: String,
}

impl VolcanoVideoService {
    /// 创建新的火山云视频生成服务实例
    pub fn new(database: Arc<Database>) -> Self {
        let repository = VideoGenerationRecordRepository::new(database.clone());
        let http_client = Client::new();
        
        // 从环境变量或配置中获取火山云密钥
        let vol_access_key = std::env::var("VOL_ACCESS_KEY_ID")
            .unwrap_or_else(|_| "AKLTZmEwYzNlZDI4NDI2NDUyNDg1ZTQ5NzVlNmQ4OGNkMDY".to_string());
        let vol_secret_key = std::env::var("VOL_ACCESS_SECRET_KEY")
            .unwrap_or_else(|_| "T1RRd1l6UTROV05pTUdRMU5EWTRNV0V4TldGak9ESmhZbVF4TnpCalpHTQ==".to_string());

        Self {
            database,
            repository,
            http_client,
            cloud_upload_service: CloudUploadService::new(),
            vol_access_key,
            vol_secret_key,
        }
    }

    /// 创建视频生成任务
    pub async fn create_video_generation(&self, request: CreateVideoGenerationRequest) -> Result<VideoGenerationRecord> {
        info!("创建视频生成任务: {}", request.name);

        // 验证输入参数
        if request.image_url.is_none() {
            return Err(anyhow!("图片URL不能为空"));
        }

        // 创建记录
        let id = Uuid::new_v4().to_string();
        let mut record = VideoGenerationRecord::new(
            id,
            request.name,
            request.image_url,
            request.audio_url,
            request.prompt,
        );

        // 设置可选参数
        if let Some(desc) = request.description {
            record.description = Some(desc);
        }
        if let Some(negative_prompt) = request.negative_prompt {
            record.negative_prompt = Some(negative_prompt);
        }
        if let Some(duration) = request.duration {
            record.duration = duration;
        }
        if let Some(fps) = request.fps {
            record.fps = fps;
        }
        if let Some(resolution) = request.resolution {
            record.resolution = resolution;
        }
        if let Some(style) = request.style {
            record.style = Some(style);
        }
        if let Some(motion_strength) = request.motion_strength {
            record.motion_strength = motion_strength;
        }

        // 保存到数据库
        self.repository.create(&record).await?;

        // 异步启动视频生成任务
        let service_clone = self.clone();
        let record_id = record.id.clone();
        tokio::spawn(async move {
            if let Err(e) = service_clone.process_video_generation(record_id).await {
                error!("视频生成任务处理失败: {}", e);
            }
        });

        Ok(record)
    }

    /// 处理视频生成任务
    async fn process_video_generation(&self, record_id: String) -> Result<()> {
        info!("开始处理视频生成任务: {}", record_id);

        // 获取记录
        let mut record = self.repository.get_by_id(&record_id).await?
            .ok_or_else(|| anyhow!("找不到视频生成记录: {}", record_id))?;

        // 标记为处理中
        record.mark_as_processing(None);
        self.repository.update(&record).await?;

        // 调用火山云API
        match self.call_volcano_api(&record).await {
            Ok(response) => {
                if let Some(data) = response.data {
                    // 更新任务ID
                    record.vol_task_id = Some(data.task_id.clone());
                    record.vol_request_id = Some(response.request_id);
                    self.repository.update(&record).await?;

                    // 轮询任务状态
                    self.poll_task_status(record_id, data.task_id).await?;
                } else {
                    record.mark_as_failed("火山云API返回数据为空".to_string(), Some("EMPTY_RESPONSE".to_string()));
                    self.repository.update(&record).await?;
                }
            }
            Err(e) => {
                error!("调用火山云API失败: {}", e);
                record.mark_as_failed(e.to_string(), Some("API_ERROR".to_string()));
                self.repository.update(&record).await?;
            }
        }

        Ok(())
    }

    /// 调用火山云视频生成API
    async fn call_volcano_api(&self, record: &VideoGenerationRecord) -> Result<VolcanoVideoGenerationResponse> {
        // 获取本地文件路径
        let image_path = record.image_url.as_ref()
            .ok_or_else(|| anyhow!("图片路径不能为空"))?;
        let driving_video_path = record.audio_url.as_ref()
            .ok_or_else(|| anyhow!("驱动视频路径不能为空，请上传驱动视频文件"))?;

        // 上传图片到云端
        info!("正在上传图片到云端: {}", image_path);
        let image_upload_result = self.cloud_upload_service
            .upload_file(image_path, None, None)
            .await?;

        if !image_upload_result.success {
            return Err(anyhow!("图片上传失败: {}",
                image_upload_result.error_message.unwrap_or_default()));
        }

        let image_s3_url = image_upload_result.remote_url
            .ok_or_else(|| anyhow!("图片上传成功但未返回URL"))?;

        // 将S3 URL转换为HTTPS CDN URL
        let image_url = Self::convert_s3_to_cdn_url(&image_s3_url);
        info!("图片S3 URL: {} -> CDN URL: {}", image_s3_url, image_url);

        // 上传驱动视频到云端
        info!("正在上传驱动视频到云端: {}", driving_video_path);
        let video_upload_result = self.cloud_upload_service
            .upload_file(driving_video_path, None, None)
            .await?;

        if !video_upload_result.success {
            return Err(anyhow!("驱动视频上传失败: {}",
                video_upload_result.error_message.unwrap_or_default()));
        }

        let driving_video_s3_url = video_upload_result.remote_url
            .ok_or_else(|| anyhow!("驱动视频上传成功但未返回URL"))?;

        // 将S3 URL转换为HTTPS CDN URL
        let driving_video_url = Self::convert_s3_to_cdn_url(&driving_video_s3_url);
        info!("驱动视频S3 URL: {} -> CDN URL: {}", driving_video_s3_url, driving_video_url);

        info!("文件上传完成 - 图片: {}, 驱动视频: {}", image_url, driving_video_url);

        let request_body = VolcanoVideoGenerationRequest {
            req_key: "realman_avatar_imitator_v2v_gen_video".to_string(),
            image_url,
            driving_video_info: DrivingVideoInfo {
                store_type: 0, // 固定值
                video_url: driving_video_url,
            },
        };

        info!("调用火山云视频生成API: {:?}", request_body);

        // 实际的火山云API调用 - 提交任务
        let api_url = "https://visual.volcengineapi.com?Action=CVSubmitTask&Version=2022-08-31";

        // 构建认证头
        let now = Utc::now();
        let timestamp = now.format("%Y%m%dT%H%M%SZ").to_string();
        let date = now.format("%Y%m%d").to_string();
        let auth_header = self.build_auth_header("POST", api_url, &timestamp, &date, &request_body)?;

        let response = self.http_client
            .post(api_url)
            .header("Authorization", auth_header)
            .header("Content-Type", "application/json")
            .header("X-Date", timestamp)
            .json(&request_body)
            .send()
            .await?;

        if !response.status().is_success() {
            let status = response.status();
            let error_text = response.text().await.unwrap_or_default();
            return Err(anyhow!("火山云API调用失败: {} - {}", status, error_text));
        }

        let api_response: VolcanoVideoGenerationResponse = response.json().await?;

        if api_response.code != 10000 {
            return Err(anyhow!("火山云API返回错误: {} - {}", api_response.code, api_response.message));
        }

        Ok(api_response)
    }

    /// 轮询任务状态
    async fn poll_task_status(&self, record_id: String, task_id: String) -> Result<()> {
        info!("开始轮询任务状态: {} - {}", record_id, task_id);

        let mut attempts = 0;
        let max_attempts = 60; // 最多轮询60次（约10分钟）
        let mut consecutive_failures = 0;
        let max_consecutive_failures = 3; // 连续失败3次就标记为失败

        while attempts < max_attempts {
            tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
            attempts += 1;

            match self.check_task_status(&task_id).await {
                Ok(status_response) => {
                    // 重置连续失败计数器
                    consecutive_failures = 0;
                    if let Some(data) = status_response.data {
                        let mut record = self.repository.get_by_id(&record_id).await?
                            .ok_or_else(|| anyhow!("找不到视频生成记录: {}", record_id))?;

                        match data.status.as_str() {
                            "done" => {
                                if let Some(video_url) = data.video_url {
                                    // 下载视频并上传到云端
                                    match self.download_and_upload_video(&video_url, &record_id).await {
                                        Ok(cdn_url) => {
                                            record.mark_as_completed(cdn_url, None); // 使用CDN URL
                                            self.repository.update(&record).await?;
                                            info!("视频生成任务完成，已上传到CDN: {}", record_id);
                                            return Ok(());
                                        }
                                        Err(e) => {
                                            warn!("视频上传到CDN失败，使用原始URL: {} - {}", record_id, e);
                                            record.mark_as_completed(video_url, None); // 使用原始URL作为fallback
                                            self.repository.update(&record).await?;
                                            info!("视频生成任务完成（使用原始URL）: {}", record_id);
                                            return Ok(());
                                        }
                                    }
                                } else {
                                    record.mark_as_failed("视频URL为空".to_string(), Some("EMPTY_VIDEO_URL".to_string()));
                                    self.repository.update(&record).await?;
                                    return Err(anyhow!("视频生成完成但视频URL为空"));
                                }
                            }
                            "not_found" => {
                                record.mark_as_failed("任务未找到".to_string(), Some("TASK_NOT_FOUND".to_string()));
                                self.repository.update(&record).await?;
                                return Err(anyhow!("火山云任务未找到"));
                            }
                            "expired" => {
                                record.mark_as_failed("任务已过期".to_string(), Some("TASK_EXPIRED".to_string()));
                                self.repository.update(&record).await?;
                                return Err(anyhow!("火山云任务已过期"));
                            }
                            "in_queue" | "generating" => {
                                // 任务还在处理中，继续轮询
                                info!("任务状态: {} - {}", data.status, record_id);
                                continue;
                            }
                            _ => {
                                warn!("未知的任务状态: {}", data.status);
                                continue;
                            }
                        }
                    }
                }
                Err(e) => {
                    warn!("检查任务状态失败: {}", e);
                    consecutive_failures += 1;

                    // 如果连续失败次数达到上限，标记任务为失败
                    if consecutive_failures >= max_consecutive_failures {
                        error!("连续{}次检查任务状态失败，标记任务为失败: {}", max_consecutive_failures, e);
                        let mut record = self.repository.get_by_id(&record_id).await?
                            .ok_or_else(|| anyhow!("找不到视频生成记录: {}", record_id))?;
                        record.mark_as_failed(
                            format!("连续{}次API调用失败: {}", max_consecutive_failures, e),
                            Some("API_CONSECUTIVE_FAILURES".to_string())
                        );
                        self.repository.update(&record).await?;
                        return Err(anyhow!("连续{}次检查任务状态失败", max_consecutive_failures));
                    }

                    continue;
                }
            }
        }

        // 超时处理
        let mut record = self.repository.get_by_id(&record_id).await?
            .ok_or_else(|| anyhow!("找不到视频生成记录: {}", record_id))?;
        record.mark_as_failed("任务超时".to_string(), Some("TIMEOUT".to_string()));
        self.repository.update(&record).await?;

        Err(anyhow!("视频生成任务超时"))
    }

    /// 检查任务状态
    async fn check_task_status(&self, task_id: &str) -> Result<VolcanoVideoQueryResponse> {
        info!("检查任务状态: {}", task_id);

        // 构建查询请求
        let request_body = VolcanoVideoQueryRequest {
            req_key: "realman_avatar_imitator_v2v_gen_video".to_string(),
            task_id: task_id.to_string(),
        };

        // 实际的火山云API调用 - 查询任务
        let api_url = "https://visual.volcengineapi.com?Action=CVGetResult&Version=2022-08-31";

        // 构建认证头
        let now = Utc::now();
        let timestamp = now.format("%Y%m%dT%H%M%SZ").to_string();
        let date = now.format("%Y%m%d").to_string();
        let auth_header = self.build_auth_header("POST", api_url, &timestamp, &date, &request_body)?;

        let response = self.http_client
            .post(api_url)
            .header("Authorization", auth_header)
            .header("Content-Type", "application/json")
            .header("X-Date", timestamp)
            .json(&request_body)
            .send()
            .await?;

        if !response.status().is_success() {
            let status = response.status();
            let error_text = response.text().await.unwrap_or_default();
            return Err(anyhow!("火山云API调用失败: {} - {}", status, error_text));
        }

        let api_response: VolcanoVideoQueryResponse = response.json().await?;

        if api_response.code != 10000 {
            return Err(anyhow!("火山云API返回错误: {} - {}", api_response.code, api_response.message));
        }

        Ok(api_response)
    }

    /// 构建火山云API认证头
    fn build_auth_header<T: Serialize>(&self, method: &str, url: &str, timestamp: &str, date: &str, body: &T) -> Result<String> {
        // 1. 创建规范请求 (CanonicalRequest)
        let canonical_request = self.create_canonical_request(method, url, timestamp, body)?;

        // 2. 创建待签名字符串 (StringToSign)
        let credential_scope = format!("{}/cn-north-1/cv/request", date);
        let string_to_sign = self.create_string_to_sign(timestamp, &credential_scope, &canonical_request)?;

        // 3. 派生签名密钥 (kSigning)
        let signing_key = self.derive_signing_key(&self.vol_secret_key, date, "cn-north-1", "cv")?;

        // 4. 计算签名 (Signature)
        let signature = self.calculate_signature(&signing_key, &string_to_sign)?;

        // 5. 构建Authorization头
        let auth_string = format!(
            "HMAC-SHA256 Credential={}/{}, SignedHeaders=host;x-date, Signature={}",
            self.vol_access_key,
            credential_scope,
            signature
        );

        Ok(auth_string)
    }

    /// 获取视频生成记录列表
    pub async fn get_video_generations(&self, query: VideoGenerationQuery) -> Result<Vec<VideoGenerationRecord>> {
        self.repository.get_list(query).await
    }

    /// 根据ID获取视频生成记录
    pub async fn get_video_generation_by_id(&self, id: &str) -> Result<Option<VideoGenerationRecord>> {
        self.repository.get_by_id(id).await
    }

    /// 删除视频生成记录
    pub async fn delete_video_generation(&self, id: &str) -> Result<()> {
        self.repository.delete(id).await
    }

    /// 批量删除视频生成记录
    pub async fn batch_delete_video_generations(&self, ids: Vec<String>) -> Result<()> {
        for id in ids {
            self.repository.delete(&id).await?;
        }
        Ok(())
    }

    /// 创建规范请求
    fn create_canonical_request<T: Serialize>(&self, method: &str, url: &str, timestamp: &str, body: &T) -> Result<String> {
        // 解析URL获取host和path
        let parsed_url = Url::parse(url)?;
        let host = parsed_url.host_str().ok_or_else(|| anyhow!("无效的URL"))?;
        let path = parsed_url.path();
        let query = parsed_url.query().unwrap_or("");

        // 规范化查询字符串
        let canonical_query_string = self.canonicalize_query_string(query);

        // 规范化请求头
        let canonical_headers = format!("host:{}\nx-date:{}\n", host, timestamp);

        // 签名的请求头
        let signed_headers = "host;x-date";

        // 计算请求体的哈希值
        let body_json = serde_json::to_string(body)?;
        let body_hash = hex::encode(Sha256::digest(body_json.as_bytes()));

        // 构建规范请求
        let canonical_request = format!(
            "{}\n{}\n{}\n{}\n{}\n{}",
            method,
            path,
            canonical_query_string,
            canonical_headers,
            signed_headers,
            body_hash
        );

        Ok(canonical_request)
    }

    /// 规范化查询字符串
    fn canonicalize_query_string(&self, query: &str) -> String {
        if query.is_empty() {
            return String::new();
        }

        let mut params: Vec<(String, String)> = query
            .split('&')
            .filter_map(|param| {
                let mut parts = param.splitn(2, '=');
                let key = parts.next()?.to_string();
                let value = parts.next().unwrap_or("").to_string();
                Some((key, value))
            })
            .collect();

        // 按参数名称的ASCII升序排序
        params.sort_by(|a, b| a.0.cmp(&b.0));

        // 构建规范化查询字符串
        params
            .into_iter()
            .map(|(key, value)| format!("{}={}", key, value))
            .collect::<Vec<_>>()
            .join("&")
    }

    /// 创建待签名字符串
    fn create_string_to_sign(&self, timestamp: &str, credential_scope: &str, canonical_request: &str) -> Result<String> {
        let canonical_request_hash = hex::encode(Sha256::digest(canonical_request.as_bytes()));

        let string_to_sign = format!(
            "HMAC-SHA256\n{}\n{}\n{}",
            timestamp,
            credential_scope,
            canonical_request_hash
        );

        Ok(string_to_sign)
    }

    /// 派生签名密钥
    fn derive_signing_key(&self, secret_key: &str, date: &str, region: &str, service: &str) -> Result<Vec<u8>> {
        type HmacSha256 = Hmac<Sha256>;

        // kDate = HMAC(kSecret, Date)
        let mut mac = HmacSha256::new_from_slice(secret_key.as_bytes())?;
        mac.update(date.as_bytes());
        let k_date = mac.finalize().into_bytes();

        // kRegion = HMAC(kDate, Region)
        let mut mac = HmacSha256::new_from_slice(&k_date)?;
        mac.update(region.as_bytes());
        let k_region = mac.finalize().into_bytes();

        // kService = HMAC(kRegion, Service)
        let mut mac = HmacSha256::new_from_slice(&k_region)?;
        mac.update(service.as_bytes());
        let k_service = mac.finalize().into_bytes();

        // kSigning = HMAC(kService, "request")
        let mut mac = HmacSha256::new_from_slice(&k_service)?;
        mac.update(b"request");
        let k_signing = mac.finalize().into_bytes();

        Ok(k_signing.to_vec())
    }

    /// 计算签名
    fn calculate_signature(&self, signing_key: &[u8], string_to_sign: &str) -> Result<String> {
        type HmacSha256 = Hmac<Sha256>;

        let mut mac = HmacSha256::new_from_slice(signing_key)?;
        mac.update(string_to_sign.as_bytes());
        let signature = mac.finalize().into_bytes();

        Ok(hex::encode(signature))
    }

    /// 下载视频并上传到云端服务
    async fn download_and_upload_video(&self, video_url: &str, record_id: &str) -> Result<String> {
        info!("开始下载并上传视频: {} -> {}", video_url, record_id);

        // 创建临时文件路径
        let temp_dir = std::env::temp_dir();
        let temp_filename = format!("volcano_video_{}_{}.mp4", record_id, chrono::Utc::now().timestamp());
        let temp_file_path = temp_dir.join(&temp_filename);
        let temp_file_str = temp_file_path.to_string_lossy().to_string();

        // 下载视频到本地临时文件
        info!("正在下载视频到临时文件: {}", temp_file_str);
        match self.download_video_to_file(video_url, &temp_file_str).await {
            Ok(_) => {
                info!("视频下载成功: {}", temp_file_str);
            }
            Err(e) => {
                error!("视频下载失败: {} - {}", video_url, e);
                return Err(anyhow!("视频下载失败: {}", e));
            }
        }

        // 上传到云端服务
        info!("正在上传视频到云端: {}", temp_file_str);
        let upload_result = match self.cloud_upload_service.upload_file(&temp_file_str, None, None).await {
            Ok(result) => result,
            Err(e) => {
                // 清理临时文件
                let _ = tokio::fs::remove_file(&temp_file_path).await;
                error!("视频上传失败: {} - {}", temp_file_str, e);
                return Err(anyhow!("视频上传失败: {}", e));
            }
        };

        // 清理临时文件
        if let Err(e) = tokio::fs::remove_file(&temp_file_path).await {
            warn!("清理临时文件失败: {} - {}", temp_file_str, e);
        }

        if !upload_result.success {
            let error_msg = upload_result.error_message.unwrap_or_default();
            error!("视频上传失败: {}", error_msg);
            return Err(anyhow!("视频上传失败: {}", error_msg));
        }

        let s3_url = upload_result.remote_url
            .ok_or_else(|| anyhow!("上传成功但未返回S3 URL"))?;

        // 转换S3 URL为CDN URL
        let cdn_url = Self::convert_s3_to_cdn_url(&s3_url);
        info!("视频上传成功: {} -> {} -> {}", video_url, s3_url, cdn_url);

        Ok(cdn_url)
    }

    /// 下载视频文件到本地
    async fn download_video_to_file(&self, video_url: &str, file_path: &str) -> Result<()> {
        // 创建带有防盗链绕过的HTTP客户端
        let client = reqwest::Client::builder()
            .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
            .timeout(std::time::Duration::from_secs(300)) // 5分钟超时
            .build()
            .map_err(|e| anyhow!("创建HTTP客户端失败: {}", e))?;

        // 构建请求，添加必要的头部信息绕过防盗链
        let request = client
            .get(video_url)
            .header("Referer", "https://www.volcengine.com/")
            .header("Origin", "https://www.volcengine.com")
            .header("Accept", "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5")
            .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
            .header("Cache-Control", "no-cache")
            .header("Pragma", "no-cache")
            .header("Sec-Fetch-Dest", "video")
            .header("Sec-Fetch-Mode", "no-cors")
            .header("Sec-Fetch-Site", "cross-site");

        let response = request.send().await
            .map_err(|e| anyhow!("请求视频失败: {}", e))?;

        if !response.status().is_success() {
            return Err(anyhow!("下载视频失败，HTTP状态码: {}", response.status()));
        }

        let bytes = response.bytes().await
            .map_err(|e| anyhow!("读取视频数据失败: {}", e))?;

        tokio::fs::write(file_path, &bytes).await
            .map_err(|e| anyhow!("保存视频文件失败: {}", e))?;

        info!("视频文件保存成功: {} ({} bytes)", file_path, bytes.len());
        Ok(())
    }

    /// 将S3 URL转换为可访问的CDN地址
    fn convert_s3_to_cdn_url(s3_url: &str) -> String {
        if s3_url.starts_with("s3://ap-northeast-2/modal-media-cache/") {
            // 将 s3://ap-northeast-2/modal-media-cache/ 替换为 https://cdn.roasmax.cn/
            s3_url.replace("s3://ap-northeast-2/modal-media-cache/", "https://cdn.roasmax.cn/")
        } else if s3_url.starts_with("s3://") {
            // 处理其他 s3:// 格式，转换为通用CDN格式
            s3_url.replace("s3://", "https://cdn.roasmax.cn/")
        } else if s3_url.contains("amazonaws.com") {
            // 如果是完整的S3 HTTPS URL，提取key部分
            if let Some(key_start) = s3_url.find(".com/") {
                let key = &s3_url[key_start + 5..];
                format!("https://cdn.roasmax.cn/{}", key)
            } else {
                s3_url.to_string()
            }
        } else {
            // 如果不是预期的S3格式，返回原URL
            s3_url.to_string()
        }
    }
}

// 实现Clone trait以支持异步任务
impl Clone for VolcanoVideoService {
    fn clone(&self) -> Self {
        Self {
            database: self.database.clone(),
            repository: VideoGenerationRecordRepository::new(self.database.clone()),
            http_client: self.http_client.clone(),
            cloud_upload_service: CloudUploadService::new(),
            vol_access_key: self.vol_access_key.clone(),
            vol_secret_key: self.vol_secret_key.clone(),
        }
    }
}
