use anyhow::{Result, anyhow};
use std::sync::Arc;
use chrono::Utc;
use std::path::Path;

use crate::data::models::template_matching_result::{
    TemplateMatchingResult, MatchingSegmentResult, MatchingFailedSegmentResult,
    CreateTemplateMatchingResultRequest, TemplateMatchingResultQueryOptions,
};
use crate::data::repositories::template_matching_result_repository::TemplateMatchingResultRepository;
use crate::business::services::material_matching_service::{
    MaterialMatchingResult as ServiceMatchingResult,
};
use crate::business::services::jianying_export::JianYingExportService;
use crate::data::repositories::material_repository::MaterialRepository;

/// 模板匹配结果服务
/// 遵循 Tauri 开发规范的业务逻辑设计原则
pub struct TemplateMatchingResultService {
    repository: Arc<TemplateMatchingResultRepository>,
}

impl TemplateMatchingResultService {
    /// 创建新的模板匹配结果服务实例
    pub fn new(repository: Arc<TemplateMatchingResultRepository>) -> Self {
        Self { repository }
    }

    /// 保存匹配结果到数据库
    /// 这是一个完整的事务操作，保存主结果和所有相关的片段信息
    pub async fn save_matching_result(
        &self,
        service_result: &ServiceMatchingResult,
        result_name: String,
        description: Option<String>,
        matching_duration_ms: u64,
    ) -> Result<TemplateMatchingResult> {
        println!("🔧 TemplateMatchingResultService::save_matching_result 开始");

        // 创建主匹配结果记录
        let create_request = CreateTemplateMatchingResultRequest {
            project_id: service_result.project_id.clone(),
            template_id: service_result.template_id.clone(),
            binding_id: service_result.binding_id.clone(),
            result_name,
            description,
        };

        println!("📝 创建主匹配结果记录...");
        let mut matching_result = self.repository.create(create_request)?;
        println!("✅ 主匹配结果记录创建成功，ID: {}", matching_result.id);

        // 更新统计信息
        println!("📊 计算统计信息...");
        let total_segments = service_result.matches.len() + service_result.failed_segments.len();
        let matched_segments = service_result.matches.len();
        let failed_segments = service_result.failed_segments.len();

        println!("📈 基础统计:");
        println!("  - total_segments: {}", total_segments);
        println!("  - matched_segments: {}", matched_segments);
        println!("  - failed_segments: {}", failed_segments);

        // 计算使用的素材和模特数量
        let mut used_material_ids = std::collections::HashSet::new();
        let mut used_model_names = std::collections::HashSet::new();

        for segment_match in &service_result.matches {
            used_material_ids.insert(segment_match.material_segment.material_id.clone());
            if let Some(model_name) = &segment_match.model_name {
                used_model_names.insert(model_name.clone());
            }
        }

        println!("📋 素材和模特统计:");
        println!("  - used_materials: {}", used_material_ids.len());
        println!("  - used_models: {}", used_model_names.len());

        matching_result.update_statistics(
            total_segments as u32,
            matched_segments as u32,
            failed_segments as u32,
            used_material_ids.len() as u32,
            used_model_names.len() as u32,
            matching_duration_ms,
        );

        // 更新主记录
        self.repository.update(&matching_result)?;

        // 保存成功匹配的片段
        let segment_results: Vec<MatchingSegmentResult> = service_result.matches
            .iter()
            .map(|segment_match| {
                let mut segment_result = MatchingSegmentResult::new(
                    uuid::Uuid::new_v4().to_string(),
                    matching_result.id.clone(),
                    segment_match.track_segment_id.clone(),
                    segment_match.track_segment_name.clone(),
                    segment_match.material_segment_id.clone(),
                    segment_match.material_segment.material_id.clone(),
                    segment_match.material_name.clone(),
                    segment_match.match_score,
                    segment_match.match_reason.clone(),
                    (segment_match.material_segment.duration * 1_000_000.0) as u64,
                    (segment_match.material_segment.start_time * 1_000_000.0) as u64,
                    (segment_match.material_segment.end_time * 1_000_000.0) as u64,
                );

                // 设置模特信息
                if let Some(model_name) = &segment_match.model_name {
                    // 这里可以通过模特名称查找模特ID，暂时使用名称作为ID
                    segment_result.set_model_info(model_name.clone(), model_name.clone());
                }

                segment_result
            })
            .collect();

        if !segment_results.is_empty() {
            self.repository.create_segment_results(&segment_results)?;
        }

        // 保存失败的片段
        let failed_segment_results: Vec<MatchingFailedSegmentResult> = service_result.failed_segments
            .iter()
            .map(|failed_segment| {
                let mut failed_result = MatchingFailedSegmentResult::new(
                    uuid::Uuid::new_v4().to_string(),
                    matching_result.id.clone(),
                    failed_segment.track_segment_id.clone(),
                    failed_segment.track_segment_name.clone(),
                    failed_segment.matching_rule.display_name(),
                    failed_segment.failure_reason.clone(),
                    0, // 这里需要从模板中获取片段时长
                    0, // 这里需要从模板中获取开始时间
                    0, // 这里需要从模板中获取结束时间
                );

                // 设置匹配规则数据
                if let Ok(rule_json) = serde_json::to_string(&failed_segment.matching_rule) {
                    failed_result.set_matching_rule_data(rule_json);
                }

                failed_result
            })
            .collect();

        if !failed_segment_results.is_empty() {
            self.repository.create_failed_segment_results(&failed_segment_results)?;
        }

        println!("✅ TemplateMatchingResultService::save_matching_result 完成，ID: {}", matching_result.id);
        Ok(matching_result)
    }

    /// 获取匹配结果详情（包含所有片段信息）
    pub async fn get_matching_result_detail(&self, result_id: &str) -> Result<Option<TemplateMatchingResultDetail>> {
        let matching_result = match self.repository.get_by_id(result_id)? {
            Some(result) => result,
            None => return Ok(None),
        };

        let segment_results = self.repository.get_segment_results_by_matching_result_id(result_id)?;
        let failed_segment_results = self.repository.get_failed_segment_results_by_matching_result_id(result_id)?;

        Ok(Some(TemplateMatchingResultDetail {
            matching_result,
            segment_results,
            failed_segment_results,
        }))
    }

    /// 获取项目的匹配结果列表
    pub async fn get_project_matching_results(&self, project_id: &str) -> Result<Vec<TemplateMatchingResult>> {
        Ok(self.repository.get_by_project_id(project_id)?)
    }

    /// 获取模板的匹配结果列表
    pub async fn get_template_matching_results(&self, template_id: &str) -> Result<Vec<TemplateMatchingResult>> {
        Ok(self.repository.get_by_template_id(template_id)?)
    }

    /// 获取绑定的匹配结果列表
    pub async fn get_binding_matching_results(&self, binding_id: &str) -> Result<Vec<TemplateMatchingResult>> {
        Ok(self.repository.get_by_binding_id(binding_id)?)
    }

    /// 查询匹配结果列表
    pub async fn list_matching_results(&self, options: TemplateMatchingResultQueryOptions) -> Result<Vec<TemplateMatchingResult>> {
        Ok(self.repository.list(options)?)
    }

    /// 删除匹配结果
    pub async fn delete_matching_result(&self, result_id: &str) -> Result<bool> {
        Ok(self.repository.delete(result_id)?)
    }

    /// 软删除匹配结果
    pub async fn soft_delete_matching_result(&self, result_id: &str) -> Result<bool> {
        Ok(self.repository.soft_delete(result_id)?)
    }

    /// 批量删除匹配结果
    pub async fn batch_delete_matching_results(&self, result_ids: &[String]) -> Result<u32> {
        let mut deleted_count = 0;

        for result_id in result_ids {
            if self.repository.delete(result_id)? {
                deleted_count += 1;
            }
        }

        Ok(deleted_count)
    }

    /// 批量软删除匹配结果
    pub async fn batch_soft_delete_matching_results(&self, result_ids: &[String]) -> Result<u32> {
        let mut deleted_count = 0;

        for result_id in result_ids {
            if self.repository.soft_delete(result_id)? {
                deleted_count += 1;
            }
        }

        Ok(deleted_count)
    }

    /// 批量删除匹配结果并重置资源使用状态
    pub async fn batch_delete_matching_results_with_usage_reset(
        &self,
        result_ids: &[String],
        material_usage_repo: Arc<crate::data::repositories::material_usage_repository::MaterialUsageRepository>
    ) -> Result<(u32, u32)> {
        // 先删除使用记录并重置资源状态
        let deleted_usage_records = material_usage_repo.delete_usage_records_by_matching_results(result_ids)?;

        // 再删除匹配结果
        let deleted_results = self.batch_delete_matching_results(result_ids).await?;

        Ok((deleted_results, deleted_usage_records))
    }

    /// 批量软删除匹配结果并重置资源使用状态
    pub async fn batch_soft_delete_matching_results_with_usage_reset(
        &self,
        result_ids: &[String],
        material_usage_repo: Arc<crate::data::repositories::material_usage_repository::MaterialUsageRepository>
    ) -> Result<(u32, u32)> {
        // 先删除使用记录并重置资源状态
        let deleted_usage_records = material_usage_repo.delete_usage_records_by_matching_results(result_ids)?;

        // 再软删除匹配结果
        let deleted_results = self.batch_soft_delete_matching_results(result_ids).await?;

        Ok((deleted_results, deleted_usage_records))
    }

    /// 更新匹配结果名称和描述
    pub async fn update_matching_result_info(
        &self,
        result_id: &str,
        result_name: Option<String>,
        description: Option<String>,
    ) -> Result<Option<TemplateMatchingResult>> {
        let mut matching_result = match self.repository.get_by_id(result_id)? {
            Some(result) => result,
            None => return Ok(None),
        };

        let mut updated = false;

        if let Some(name) = result_name {
            matching_result.result_name = name;
            updated = true;
        }

        if let Some(desc) = description {
            matching_result.set_description(desc);
            updated = true;
        }

        if updated {
            matching_result.updated_at = Utc::now();
            self.repository.update(&matching_result)?;
        }

        Ok(Some(matching_result))
    }

    /// 设置匹配结果质量评分
    pub async fn set_quality_score(&self, result_id: &str, quality_score: f64) -> Result<Option<TemplateMatchingResult>> {
        let mut matching_result = match self.repository.get_by_id(result_id)? {
            Some(result) => result,
            None => return Ok(None),
        };

        matching_result.set_quality_score(quality_score);
        self.repository.update(&matching_result)?;

        Ok(Some(matching_result))
    }

    /// 获取匹配结果统计信息
    pub async fn get_matching_statistics(&self, project_id: Option<&str>) -> Result<MatchingStatistics> {
        let options = TemplateMatchingResultQueryOptions {
            project_id: project_id.map(|id| id.to_string()),
            ..Default::default()
        };

        let results = self.repository.list(options)?;

        let total_results = results.len();
        let successful_results = results.iter().filter(|r| r.is_successful()).count();
        let total_segments: u32 = results.iter().map(|r| r.total_segments).sum();
        let matched_segments: u32 = results.iter().map(|r| r.matched_segments).sum();
        let total_materials: u32 = results.iter().map(|r| r.used_materials).sum();
        let total_models: u32 = results.iter().map(|r| r.used_models).sum();

        let average_success_rate = if total_results > 0 {
            results.iter().map(|r| r.success_rate).sum::<f64>() / total_results as f64
        } else {
            0.0
        };

        Ok(MatchingStatistics {
            total_results,
            successful_results,
            total_segments,
            matched_segments,
            total_materials,
            total_models,
            average_success_rate,
        })
    }
}

/// 模板匹配结果详情
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TemplateMatchingResultDetail {
    pub matching_result: TemplateMatchingResult,
    pub segment_results: Vec<MatchingSegmentResult>,
    pub failed_segment_results: Vec<MatchingFailedSegmentResult>,
}

/// 匹配统计信息
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MatchingStatistics {
    pub total_results: usize,
    pub successful_results: usize,
    pub total_segments: u32,
    pub matched_segments: u32,
    pub total_materials: u32,
    pub total_models: u32,
    pub average_success_rate: f64,
}

impl TemplateMatchingResultService {
    /// 清理Windows路径格式，移除UNC前缀
    fn normalize_windows_path(path: &str) -> String {
        // 移除 \\?\ 前缀（Windows长路径UNC格式）
        if path.starts_with("\\\\?\\") {
            path.strip_prefix("\\\\?\\").unwrap_or(path).to_string()
        } else {
            path.to_string()
        }
    }
    /// 导出匹配结果到剪映格式 (V1版本)
    /// 根据模板匹配结果生成剪映可导入的 draft_content.json 文件
    pub async fn export_to_jianying(
        &self,
        result_id: &str,
        output_path: &str,
        material_repository: Arc<MaterialRepository>,
    ) -> Result<String> {
        // 获取匹配结果详情
        let detail = self.get_matching_result_detail(result_id).await?
            .ok_or_else(|| anyhow!("匹配结果不存在: {}", result_id))?;

        // 创建基础的剪映草稿内容
        let mut draft_content = JianYingExportService::create_default_draft_content();

        // 设置基本信息
        draft_content.duration = self.calculate_total_duration(&detail)?;

        // 生成素材列表 - 替换匹配的素材路径
        let (materials, material_id_map) = self.generate_materials(&detail, material_repository).await?;
        draft_content.materials.videos = materials;

        // 生成轨道和片段
        let tracks = self.generate_tracks(&detail, &material_id_map)?;
        draft_content.tracks = tracks;

        // 生成输出文件路径
        let output_file_path = if output_path.ends_with(".json") {
            output_path.to_string()
        } else {
            format!("{}/draft_content_{}.json", output_path, result_id)
        };

        // 序列化并写入文件
        let json_content = serde_json::to_string_pretty(&draft_content)
            .map_err(|e| anyhow!("序列化失败: {}", e))?;

        std::fs::write(&output_file_path, json_content)
            .map_err(|e| anyhow!("写入文件失败: {}", e))?;

        // 更新导出状态
        self.repository.increment_export_count(result_id)?;

        println!("✅ 导出成功: {}", output_file_path);
        Ok(output_file_path)
    }

    /// 导出匹配结果到剪映格式 (V2版本)
    /// 基于原始模板的 draft_content.json 文件，替换匹配的素材和片段
    pub async fn export_to_jianying_v2(
        &self,
        result_id: &str,
        output_path: &str,
        material_repository: Arc<MaterialRepository>,
        template_service: Arc<crate::business::services::template_service::TemplateService>,
    ) -> Result<String> {
        // 第一步：获取匹配结果详情
        let detail = self.get_matching_result_detail(result_id).await?
            .ok_or_else(|| anyhow!("匹配结果不存在: {}", result_id))?;

        // 第二步：获取模板信息，读取原始 draft_content.json 文件
        let template = template_service.get_template_by_id(&detail.matching_result.template_id).await?
            .ok_or_else(|| anyhow!("模板不存在: {}", detail.matching_result.template_id))?;

        let source_file_path = template.source_file_path
            .ok_or_else(|| anyhow!("模板缺少原始文件路径"))?;

        // 读取原始 draft_content.json 文件到内存
        let original_content = std::fs::read_to_string(&source_file_path)
            .map_err(|e| anyhow!("无法读取原始模板文件 {}: {}", source_file_path, e))?;

        let mut draft_content: serde_json::Value = serde_json::from_str(&original_content)
            .map_err(|e| anyhow!("解析原始模板文件失败: {}", e))?;

        // 第三步：根据匹配记录替换模板素材片段和素材
        self.replace_materials_and_segments_v2(&mut draft_content, &detail, material_repository).await?;

        // 第四步：生成输出文件路径并保存
        let output_file_path = if output_path.ends_with(".json") {
            output_path.to_string()
        } else {
            format!("{}/draft_content.json", output_path)
        };

        // 序列化并写入文件
        let json_content = serde_json::to_string_pretty(&draft_content)
            .map_err(|e| anyhow!("序列化失败: {}", e))?;

        std::fs::write(&output_file_path, json_content)
            .map_err(|e| anyhow!("写入文件失败 {}: {}", output_file_path, e))?;

        // 更新导出状态
        self.repository.increment_export_count(result_id)?;

        println!("✅ 导出成功: {}", output_file_path);
        Ok(output_file_path)
    }

    /// 替换素材和片段 (V2版本核心逻辑)
    async fn replace_materials_and_segments_v2(
        &self,
        draft_content: &mut serde_json::Value,
        detail: &TemplateMatchingResultDetail,
        material_repository: Arc<MaterialRepository>,
    ) -> Result<()> {
        use std::collections::HashMap;

        // 构建匹配映射表：模板素材ID -> 匹配的素材信息
        let mut material_replacement_map: HashMap<String, (String, String)> = HashMap::new(); // template_material_id -> (new_path, new_material_id)
        let mut segment_replacement_map: HashMap<String, String> = HashMap::new(); // track_segment_id -> material_segment_id

        // 收集所有需要替换的素材和片段信息
        for segment_result in &detail.segment_results {
            // 获取素材片段信息
            let material_segment = material_repository.get_segment_by_id(&segment_result.material_segment_id).await?
                .ok_or_else(|| anyhow!("素材片段不存在: {}", segment_result.material_segment_id))?;

            let material = material_repository.get_by_id(&material_segment.material_id)?
                .ok_or_else(|| anyhow!("素材不存在: {}", material_segment.material_id))?;

            // 清理文件路径
            let cleaned_path = Self::normalize_windows_path(&material.original_path);

            // 记录片段替换映射
            segment_replacement_map.insert(
                segment_result.track_segment_id.clone(),
                segment_result.material_segment_id.clone()
            );

            // 记录素材替换映射 (通过track_segment找到对应的template_material_id)
            // 这里需要通过模板数据找到track_segment对应的template_material_id
            // 暂时使用segment_result中的信息
            if let Some(template_material_id) = self.find_template_material_id_for_segment(&segment_result.track_segment_id, draft_content)? {
                material_replacement_map.insert(
                    template_material_id,
                    (cleaned_path, uuid::Uuid::new_v4().to_string())
                );
            }
        }

        // 替换素材列表
        self.replace_materials_in_draft_v2(draft_content, &material_replacement_map)?;

        // 替换轨道片段
        self.replace_segments_in_tracks_v2(draft_content, &segment_replacement_map, &material_replacement_map)?;

        Ok(())
    }

    /// 查找轨道片段对应的模板素材ID
    fn find_template_material_id_for_segment(
        &self,
        track_segment_id: &str,
        draft_content: &serde_json::Value,
    ) -> Result<Option<String>> {
        // 在tracks中查找对应的segment，获取其material_id
        if let Some(tracks) = draft_content.get("tracks").and_then(|t| t.as_array()) {
            for track in tracks {
                if let Some(segments) = track.get("segments").and_then(|s| s.as_array()) {
                    for segment in segments {
                        if let Some(segment_id) = segment.get("id").and_then(|id| id.as_str()) {
                            if segment_id == track_segment_id {
                                if let Some(material_id) = segment.get("material_id").and_then(|id| id.as_str()) {
                                    return Ok(Some(material_id.to_string()));
                                }
                            }
                        }
                    }
                }
            }
        }
        Ok(None)
    }

    /// 替换草稿内容中的素材列表
    fn replace_materials_in_draft_v2(
        &self,
        draft_content: &mut serde_json::Value,
        material_replacement_map: &std::collections::HashMap<String, (String, String)>,
    ) -> Result<()> {
        // 替换 materials.videos 中的素材
        if let Some(materials) = draft_content.get_mut("materials") {
            if let Some(videos) = materials.get_mut("videos").and_then(|v| v.as_array_mut()) {
                for video in videos {
                    if let Some(video_id) = video.get("id").and_then(|id| id.as_str()) {
                        if let Some((new_path, _new_id)) = material_replacement_map.get(video_id) {
                            // 替换路径
                            video["path"] = serde_json::Value::String(new_path.clone());
                            // 可选：替换ID（如果需要）
                            // video["id"] = serde_json::Value::String(new_id.clone());

                            // 更新material_name为文件名
                            if let Some(file_name) = std::path::Path::new(new_path).file_name() {
                                if let Some(name_str) = file_name.to_str() {
                                    video["material_name"] = serde_json::Value::String(name_str.to_string());
                                }
                            }
                        }
                    }
                }
            }
        }
        Ok(())
    }

    /// 替换轨道中的片段信息
    fn replace_segments_in_tracks_v2(
        &self,
        draft_content: &mut serde_json::Value,
        segment_replacement_map: &std::collections::HashMap<String, String>,
        _material_replacement_map: &std::collections::HashMap<String, (String, String)>,
    ) -> Result<()> {
        if let Some(tracks) = draft_content.get_mut("tracks").and_then(|t| t.as_array_mut()) {
            for track in tracks {
                if let Some(segments) = track.get_mut("segments").and_then(|s| s.as_array_mut()) {
                    for segment in segments {
                        if let Some(segment_id) = segment.get("id").and_then(|id| id.as_str()) {
                            // 检查是否需要替换这个片段
                            if segment_replacement_map.contains_key(segment_id) {
                                // 这个片段需要被替换，但在V2版本中我们保持原有的片段结构
                                // 只更新material_id对应的素材路径（已在materials中处理）

                                // 可以在这里添加其他片段级别的替换逻辑
                                // 比如更新时间范围、效果等
                                println!("🔄 替换片段: {} -> 使用匹配的素材", segment_id);
                            }
                        }
                    }
                }
            }
        }
        Ok(())
    }

    /// 计算总时长
    fn calculate_total_duration(&self, detail: &TemplateMatchingResultDetail) -> Result<u64> {
        let mut total_duration = 0u64;

        for segment_result in &detail.segment_results {
            if segment_result.end_time > total_duration {
                total_duration = segment_result.end_time;
            }
        }

        Ok(total_duration)
    }

    /// 生成素材列表，替换匹配的素材路径
    async fn generate_materials(
        &self,
        detail: &TemplateMatchingResultDetail,
        material_repository: Arc<MaterialRepository>,
    ) -> Result<(Vec<crate::business::services::jianying_export::JianYingVideo>, std::collections::HashMap<String, String>)> {
        use crate::business::services::jianying_export::*;
        use std::collections::HashMap;
        use uuid::Uuid;

        let mut videos = Vec::new();
        let mut material_id_map = HashMap::new();

        for segment_result in &detail.segment_results {
            // 为每个匹配的素材生成新的UUID
            let new_material_id = Uuid::new_v4().to_string();
            material_id_map.insert(segment_result.track_segment_id.clone(), new_material_id.clone());

            // 查询MaterialSegment获取文件路径
            let material_segment = material_repository.get_segment_by_id_sync(&segment_result.material_segment_id)?
                .ok_or_else(|| anyhow!("找不到素材片段: {}", segment_result.material_segment_id))?;

            // 清理文件路径格式
            let normalized_path = Self::normalize_windows_path(&material_segment.file_path);

            // 创建剪映视频素材
            let video = JianYingVideo {
                aigc_type: "none".to_string(),
                audio_fade: None,
                cartoon_path: String::new(),
                category_id: String::new(),
                category_name: "local".to_string(),
                check_flag: 63487,
                crop: JianYingCrop {
                    lower_left_x: 0.0,
                    lower_left_y: 1.0,
                    lower_right_x: 1.0,
                    lower_right_y: 1.0,
                    upper_left_x: 0.0,
                    upper_left_y: 0.0,
                    upper_right_x: 1.0,
                    upper_right_y: 0.0,
                },
                crop_ratio: "free".to_string(),
                crop_scale: 1.0,
                duration: segment_result.segment_duration,
                extra_type_option: 0,
                formula_id: String::new(),
                freeze: None,
                has_audio: false,
                height: 1920, // 默认高度
                id: new_material_id,
                intensifies_audio_path: String::new(),
                intensifies_path: String::new(),
                is_ai_generate_content: false,
                is_copyright: true,
                is_text_edit_overdub: false,
                is_unified_beauty_mode: false,
                local_id: String::new(),
                local_material_id: Uuid::new_v4().to_string(),
                material_id: String::new(),
                material_name: Path::new(&normalized_path)
                    .file_name()
                    .and_then(|n| n.to_str())
                    .unwrap_or("unknown.mp4")
                    .to_string(),
                material_url: String::new(),
                matting: JianYingMatting {
                    flag: 0,
                    has_use_quick_brush: false,
                    has_use_quick_eraser: false,
                    interactive_time: vec![],
                    path: String::new(),
                    strokes: vec![],
                },
                media_path: String::new(),
                object_locked: None,
                origin_material_id: String::new(),
                path: normalized_path.clone(), // 使用清理后的素材路径
                picture_from: "none".to_string(),
                picture_set_category_id: String::new(),
                picture_set_category_name: String::new(),
                request_id: String::new(),
                reverse_intensifies_path: String::new(),
                reverse_path: String::new(),
                smart_motion: None,
                source: 0,
                source_platform: 0,
                stable: JianYingStable {
                    matrix_path: String::new(),
                    stable_level: 0,
                    time_range: JianYingTimeRange {
                        duration: 0,
                        start: 0,
                    },
                },
                team_id: String::new(),
                video_type: "video".to_string(),
                video_algorithm: JianYingVideoAlgorithm {
                    algorithms: vec![],
                    complement_frame_config: None,
                    deflicker: None,
                    gameplay_configs: vec![],
                    motion_blur_config: None,
                    noise_reduction: None,
                    path: String::new(),
                    quality_enhance: None,
                    time_range: None,
                },
                width: 1080, // 默认宽度
            };

            videos.push(video);
        }

        Ok((videos, material_id_map))
    }

    /// 生成轨道和片段
    fn generate_tracks(
        &self,
        detail: &TemplateMatchingResultDetail,
        material_id_map: &std::collections::HashMap<String, String>,
    ) -> Result<Vec<crate::business::services::jianying_export::JianYingTrack>> {
        use crate::business::services::jianying_export::*;
        use uuid::Uuid;

        let mut tracks = Vec::new();

        // 创建主视频轨道
        let track_id = Uuid::new_v4().to_string();
        let mut segments = Vec::new();

        for segment_result in &detail.segment_results {
            if let Some(material_id) = material_id_map.get(&segment_result.track_segment_id) {
                let segment = JianYingSegment {
                    caption_info: None,
                    cartoon: false,
                    clip: JianYingClip {
                        alpha: 1.0,
                        flip: JianYingFlip {
                            horizontal: false,
                            vertical: false,
                        },
                        rotation: 0.0,
                        scale: JianYingScale { x: 1.0, y: 1.0 },
                        transform: JianYingTransform { x: 0.0, y: 0.0 },
                    },
                    common_keyframes: vec![],
                    enable_adjust: true,
                    enable_color_correct_adjust: false,
                    enable_color_curves: true,
                    enable_color_match_adjust: false,
                    enable_color_wheels: true,
                    enable_lut: true,
                    enable_smart_color_adjust: false,
                    extra_material_refs: vec![],
                    group_id: String::new(),
                    hdr_settings: JianYingHdrSettings {
                        intensity: 1.0,
                        mode: 1,
                        nits: 1000,
                    },
                    id: Uuid::new_v4().to_string(),
                    intensifies_audio: false,
                    is_placeholder: false,
                    is_tone_modify: false,
                    keyframe_refs: vec![],
                    last_nonzero_volume: 1.0,
                    material_id: material_id.clone(),
                    render_index: 0,
                    responsive_layout: JianYingResponsiveLayout {
                        enable: false,
                        horizontal_pos_layout: 0,
                        size_layout: 0,
                        target_follow: String::new(),
                        vertical_pos_layout: 0,
                    },
                    reverse: false,
                    source_timerange: JianYingTimeRange {
                        duration: segment_result.segment_duration,
                        start: 0, // 从素材开始位置
                    },
                    speed: 1.0, // 默认播放速度
                    target_timerange: JianYingTimeRange {
                        duration: segment_result.segment_duration,
                        start: segment_result.start_time,
                    },
                    template_id: String::new(),
                    template_scene: "default".to_string(),
                    track_attribute: 0,
                    track_render_index: 0,
                    uniform_scale: JianYingUniformScale {
                        on: true,
                        value: 1.0,
                    },
                    visible: true,
                    volume: 1.0,
                };

                segments.push(segment);
            }
        }

        let track = JianYingTrack {
            attribute: 0,
            flag: 0,
            id: track_id,
            is_default_name: true,
            name: String::new(),
            segments,
        };

        tracks.push(track);
        Ok(tracks)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;

    #[test]
    fn test_find_template_material_id_for_segment() {
        let service = TemplateMatchingResultService::new(Arc::new(
            crate::data::repositories::template_matching_result_repository::TemplateMatchingResultRepository::new(
                Arc::new(crate::infrastructure::database::Database::new_with_path(":memory:").unwrap())
            )
        ));

        // 创建测试用的 draft_content JSON
        let draft_content = json!({
            "tracks": [
                {
                    "segments": [
                        {
                            "id": "segment-1",
                            "material_id": "material-1"
                        },
                        {
                            "id": "segment-2",
                            "material_id": "material-2"
                        }
                    ]
                }
            ]
        });

        // 测试查找存在的片段
        let result = service.find_template_material_id_for_segment("segment-1", &draft_content);
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), Some("material-1".to_string()));

        // 测试查找不存在的片段
        let result = service.find_template_material_id_for_segment("segment-999", &draft_content);
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), None);
    }

    #[test]
    fn test_replace_materials_in_draft_v2() {
        let service = TemplateMatchingResultService::new(Arc::new(
            crate::data::repositories::template_matching_result_repository::TemplateMatchingResultRepository::new(
                Arc::new(crate::infrastructure::database::Database::new_with_path(":memory:").unwrap())
            )
        ));

        let mut draft_content = json!({
            "materials": {
                "videos": [
                    {
                        "id": "video-1",
                        "path": "/old/path/video1.mp4",
                        "material_name": "old_video1.mp4"
                    },
                    {
                        "id": "video-2",
                        "path": "/old/path/video2.mp4",
                        "material_name": "old_video2.mp4"
                    }
                ]
            }
        });

        let mut replacement_map = std::collections::HashMap::new();
        replacement_map.insert("video-1".to_string(), ("/new/path/new_video1.mp4".to_string(), "new-id-1".to_string()));

        let result = service.replace_materials_in_draft_v2(&mut draft_content, &replacement_map);
        assert!(result.is_ok());

        // 验证替换结果
        let videos = draft_content["materials"]["videos"].as_array().unwrap();
        assert_eq!(videos[0]["path"].as_str().unwrap(), "/new/path/new_video1.mp4");
        assert_eq!(videos[0]["material_name"].as_str().unwrap(), "new_video1.mp4");

        // 未替换的素材应该保持不变
        assert_eq!(videos[1]["path"].as_str().unwrap(), "/old/path/video2.mp4");
    }
}



