use serde::{Deserialize, Serialize};
use anyhow::{Result, anyhow};
use std::collections::HashMap;
use std::path::Path;

use crate::data::models::template::{
    Template, TemplateMaterial, Track, TrackSegment, CanvasConfig,
    TemplateMaterialType, TrackType
};

/// 剪映草稿内容解析器
/// 遵循 Tauri 开发规范的业务逻辑设计原则
pub struct DraftContentParser;

/// 剪映草稿原始数据结构
#[derive(Debug, Deserialize)]
pub struct DraftContentRaw {
    pub id: String,
    pub canvas_config: CanvasConfigRaw,
    pub duration: u64,
    pub fps: f64,
    pub materials: MaterialsRaw,
    pub tracks: Option<Vec<TrackRaw>>,
}

#[derive(Debug, Deserialize)]
pub struct CanvasConfigRaw {
    pub width: u32,
    pub height: u32,
    pub ratio: String,
}

#[derive(Debug, Deserialize)]
pub struct MaterialsRaw {
    pub videos: Option<Vec<VideoMaterialRaw>>,
    pub audios: Option<Vec<AudioMaterialRaw>>,
    pub images: Option<Vec<ImageMaterialRaw>>,
    pub texts: Option<Vec<TextMaterialRaw>>,
    pub stickers: Option<Vec<StickerMaterialRaw>>,
    pub effects: Option<Vec<EffectMaterialRaw>>,
    pub canvases: Option<Vec<CanvasMaterialRaw>>,
}

#[derive(Debug, Deserialize)]
pub struct VideoMaterialRaw {
    pub id: String,
    pub local_material_id: Option<String>,
    pub material_name: Option<String>,
    pub path: String,
    pub duration: Option<u64>,
    pub width: Option<u32>,
    pub height: Option<u32>,
    pub has_audio: Option<bool>,
    #[serde(rename = "type")]
    pub material_type: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct AudioMaterialRaw {
    pub id: String,
    pub local_material_id: Option<String>,
    pub name: String,
    pub path: String,
    pub duration: Option<u64>,
    #[serde(rename = "type")]
    pub material_type: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct ImageMaterialRaw {
    pub id: String,
    pub local_material_id: Option<String>,
    pub material_name: Option<String>,
    pub path: Option<String>,
    pub width: Option<u32>,
    pub height: Option<u32>,
    #[serde(rename = "type")]
    pub material_type: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct TextMaterialRaw {
    pub id: String,
    pub content: Option<String>,
    pub font_family: Option<String>,
    pub font_size: Option<f64>,
    pub color: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct StickerMaterialRaw {
    pub id: String,
    pub name: Option<String>,
    pub path: Option<String>,
    #[serde(rename = "type")]
    pub material_type: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct EffectMaterialRaw {
    pub id: String,
    pub name: Option<String>,
    pub path: Option<String>,
    #[serde(rename = "type")]
    pub material_type: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct CanvasMaterialRaw {
    pub id: String,
    pub color: Option<String>,
    pub image: Option<String>,
    #[serde(rename = "type")]
    pub material_type: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct TrackRaw {
    pub id: String,
    #[serde(rename = "type")]
    pub track_type: String,
    pub segments: Vec<SegmentRaw>,
}

#[derive(Debug, Deserialize)]
pub struct SegmentRaw {
    pub id: String,
    pub material_id: String,
    pub target_timerange: TimeRangeRaw,
    #[serde(default)]
    pub source_timerange: Option<TimeRangeRaw>,
    #[serde(default)]
    pub speed: Option<f64>,
    #[serde(default)]
    pub visible: Option<bool>,
    #[serde(default)]
    pub volume: Option<f64>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct TimeRangeRaw {
    pub start: u64,
    pub duration: u64,
}

/// 解析结果
#[derive(Debug)]
pub struct ParseResult {
    pub template: Template,
    pub missing_files: Vec<String>,
    pub warnings: Vec<String>,
}

impl DraftContentParser {
    /// 解析剪映草稿文件
    pub fn parse_file(file_path: &str, template_name: Option<String>) -> Result<ParseResult> {
        let content = std::fs::read_to_string(file_path)
            .map_err(|e| anyhow!("无法读取文件 {}: {}", file_path, e))?;
        
        Self::parse_content(&content, template_name, Some(file_path.to_string()))
    }

    /// 解析剪映草稿内容
    pub fn parse_content(
        content: &str, 
        template_name: Option<String>,
        source_file_path: Option<String>
    ) -> Result<ParseResult> {
        let draft: DraftContentRaw = serde_json::from_str(content)
            .map_err(|e| anyhow!("JSON解析失败: {}", e))?;

        let mut missing_files = Vec::new();
        let mut warnings = Vec::new();

        // 创建模板基础信息
        let canvas_config = CanvasConfig {
            width: draft.canvas_config.width,
            height: draft.canvas_config.height,
            ratio: draft.canvas_config.ratio,
        };

        let name = template_name.unwrap_or_else(|| {
            source_file_path
                .as_ref()
                .and_then(|p| Path::new(p).file_stem())
                .and_then(|s| s.to_str())
                .unwrap_or("未命名模板")
                .to_string()
        });

        let mut template = Template::new(name, canvas_config, draft.duration, draft.fps);
        // 使用草稿文件中的ID作为模板ID，确保同一个草稿文件导入时不会重复
        template.id = draft.id.clone();
        template.source_file_path = source_file_path;

        // 解析素材
        let mut materials = Self::parse_materials(&draft.materials, &mut missing_files, &mut warnings)?;

        // 设置素材的模板ID
        for material in &mut materials {
            material.template_id = template.id.clone();
        }

        // 构建素材映射表：素材ID -> 素材ID (用于片段关联)
        // 片段的 material_id 直接对应 template_materials.id
        let material_map: HashMap<String, String> = materials
            .iter()
            .map(|m| (m.id.clone(), m.id.clone()))  // 键是素材ID，值也是素材ID
            .collect();

        for material in materials {
            template.add_material(material);
        }

        // 解析轨道（如果存在）
        if let Some(tracks_raw) = draft.tracks {
            for (index, track_raw) in tracks_raw.iter().enumerate() {
                let track = Self::parse_track(
                    track_raw, 
                    &template.id, 
                    index as u32, 
                    &material_map,
                    &mut warnings
                )?;
                template.add_track(track);
            }
        }

        Ok(ParseResult {
            template,
            missing_files,
            warnings,
        })
    }

    /// 解析素材集合
    fn parse_materials(
        materials: &MaterialsRaw,
        missing_files: &mut Vec<String>,
        warnings: &mut Vec<String>,
    ) -> Result<Vec<TemplateMaterial>> {
        let mut result = Vec::new();

        // 解析视频素材
        if let Some(videos) = &materials.videos {
            for video in videos {
                match Self::parse_video_material(video, missing_files) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("视频素材解析失败 {}: {}", video.id, e)),
                }
            }
        }

        // 解析音频素材
        if let Some(audios) = &materials.audios {
            for audio in audios {
                match Self::parse_audio_material(audio, missing_files) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("音频素材解析失败 {}: {}", audio.id, e)),
                }
            }
        }

        // 解析图片素材
        if let Some(images) = &materials.images {
            for image in images {
                match Self::parse_image_material(image, missing_files) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("图片素材解析失败 {}: {}", image.id, e)),
                }
            }
        }

        // 解析文本素材
        if let Some(texts) = &materials.texts {
            for text in texts {
                match Self::parse_text_material(text) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("文本素材解析失败 {}: {}", text.id, e)),
                }
            }
        }

        // 解析贴纸素材
        if let Some(stickers) = &materials.stickers {
            for sticker in stickers {
                match Self::parse_sticker_material(sticker, missing_files) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("贴纸素材解析失败 {}: {}", sticker.id, e)),
                }
            }
        }

        // 解析特效素材
        if let Some(effects) = &materials.effects {
            for effect in effects {
                match Self::parse_effect_material(effect, missing_files) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("特效素材解析失败 {}: {}", effect.id, e)),
                }
            }
        }

        // 解析画布素材
        if let Some(canvases) = &materials.canvases {
            for canvas in canvases {
                match Self::parse_canvas_material(canvas) {
                    Ok(material) => result.push(material),
                    Err(e) => warnings.push(format!("画布素材解析失败 {}: {}", canvas.id, e)),
                }
            }
        }

        Ok(result)
    }

    /// 解析视频素材
    fn parse_video_material(
        video: &VideoMaterialRaw,
        missing_files: &mut Vec<String>,
    ) -> Result<TemplateMaterial> {
        let name = video.material_name.clone().unwrap_or_else(|| {
            Path::new(&video.path)
                .file_name()
                .and_then(|s| s.to_str())
                .unwrap_or("未知视频")
                .to_string()
        });

        // 检查文件是否存在
        if !Path::new(&video.path).exists() {
            missing_files.push(video.path.clone());
        }

        // original_id 使用 local_material_id，如果没有则使用空字符串
        let original_id = video.local_material_id.clone()
            .filter(|id| !id.is_empty())
            .unwrap_or_default();

        let mut material = TemplateMaterial::new(
            video.id.clone(), // 使用素材的真实ID
            String::new(),    // template_id 稍后设置
            original_id,      // original_id 对应 local_material_id
            name,
            TemplateMaterialType::Video,
            video.path.clone(),
        );

        material.duration = video.duration;
        material.width = video.width;
        material.height = video.height;

        // 设置文件大小（如果文件存在）
        if let Ok(metadata) = std::fs::metadata(&video.path) {
            material.file_size = Some(metadata.len());
        }

        Ok(material)
    }

    /// 解析音频素材
    fn parse_audio_material(
        audio: &AudioMaterialRaw,
        missing_files: &mut Vec<String>,
    ) -> Result<TemplateMaterial> {
        // 检查文件是否存在
        if !Path::new(&audio.path).exists() {
            missing_files.push(audio.path.clone());
        }

        // original_id 使用 local_material_id，如果没有则使用空字符串
        let original_id = audio.local_material_id.clone()
            .filter(|id| !id.is_empty())
            .unwrap_or_default();

        let mut material = TemplateMaterial::new(
            audio.id.clone(), // 使用素材的真实ID
            String::new(),    // template_id 稍后设置
            original_id,      // original_id 对应 local_material_id
            audio.name.clone(),
            TemplateMaterialType::Audio,
            audio.path.clone(),
        );

        material.duration = audio.duration;

        // 设置文件大小（如果文件存在）
        if let Ok(metadata) = std::fs::metadata(&audio.path) {
            material.file_size = Some(metadata.len());
        }

        Ok(material)
    }

    /// 解析图片素材
    fn parse_image_material(
        image: &ImageMaterialRaw,
        missing_files: &mut Vec<String>,
    ) -> Result<TemplateMaterial> {
        let path = image.path.clone().unwrap_or_default();
        let name = image.material_name.clone().unwrap_or_else(|| {
            if path.is_empty() {
                "未知图片".to_string()
            } else {
                Path::new(&path)
                    .file_name()
                    .and_then(|s| s.to_str())
                    .unwrap_or("未知图片")
                    .to_string()
            }
        });

        // 检查文件是否存在（如果有路径）
        if !path.is_empty() && !Path::new(&path).exists() {
            missing_files.push(path.clone());
        }

        // original_id 使用 local_material_id，如果没有则使用空字符串
        let original_id = image.local_material_id.clone()
            .filter(|id| !id.is_empty())
            .unwrap_or_default();

        let mut material = TemplateMaterial::new(
            image.id.clone(), // 使用素材的真实ID
            String::new(),    // template_id 稍后设置
            original_id,      // original_id 对应 local_material_id
            name,
            TemplateMaterialType::Image,
            path,
        );

        material.width = image.width;
        material.height = image.height;

        // 设置文件大小（如果文件存在）
        if !material.original_path.is_empty() {
            if let Ok(metadata) = std::fs::metadata(&material.original_path) {
                material.file_size = Some(metadata.len());
            }
        }

        Ok(material)
    }

    /// 解析文本素材
    fn parse_text_material(text: &TextMaterialRaw) -> Result<TemplateMaterial> {
        let name = text.content.clone().unwrap_or_else(|| "文本".to_string());

        let mut material = TemplateMaterial::new(
            text.id.clone(), // 使用素材的真实ID
            String::new(),   // template_id 稍后设置
            String::new(),   // 文字素材没有 local_material_id
            name,
            TemplateMaterialType::Text,
            String::new(),   // 文本素材没有文件路径
        );

        // 将文本属性存储为元数据
        let metadata = serde_json::json!({
            "content": text.content,
            "font_family": text.font_family,
            "font_size": text.font_size,
            "color": text.color
        });
        material.metadata = Some(metadata.to_string());

        Ok(material)
    }

    /// 解析贴纸素材
    fn parse_sticker_material(
        sticker: &StickerMaterialRaw,
        missing_files: &mut Vec<String>,
    ) -> Result<TemplateMaterial> {
        let path = sticker.path.clone().unwrap_or_default();
        let name = sticker.name.clone().unwrap_or_else(|| "贴纸".to_string());

        // 检查文件是否存在（如果有路径）
        if !path.is_empty() && !Path::new(&path).exists() {
            missing_files.push(path.clone());
        }

        let mut material = TemplateMaterial::new(
            sticker.id.clone(), // 使用素材的真实ID
            String::new(),      // template_id 稍后设置
            String::new(),      // 贴纸素材没有 local_material_id
            name,
            TemplateMaterialType::Sticker,
            path,
        );

        // 设置文件大小（如果文件存在）
        if !material.original_path.is_empty() {
            if let Ok(metadata) = std::fs::metadata(&material.original_path) {
                material.file_size = Some(metadata.len());
            }
        }

        Ok(material)
    }

    /// 解析特效素材
    fn parse_effect_material(
        effect: &EffectMaterialRaw,
        missing_files: &mut Vec<String>,
    ) -> Result<TemplateMaterial> {
        let path = effect.path.clone().unwrap_or_default();
        let name = effect.name.clone().unwrap_or_else(|| "特效".to_string());

        // 检查文件是否存在（如果有路径）
        if !path.is_empty() && !Path::new(&path).exists() {
            missing_files.push(path.clone());
        }

        let mut material = TemplateMaterial::new(
            effect.id.clone(), // 使用素材的真实ID
            String::new(),     // template_id 稍后设置
            String::new(),     // 特效素材没有 local_material_id
            name,
            TemplateMaterialType::Effect,
            path,
        );

        // 设置文件大小（如果文件存在）
        if !material.original_path.is_empty() {
            if let Ok(metadata) = std::fs::metadata(&material.original_path) {
                material.file_size = Some(metadata.len());
            }
        }

        Ok(material)
    }

    /// 解析画布素材
    fn parse_canvas_material(canvas: &CanvasMaterialRaw) -> Result<TemplateMaterial> {
        let name = "画布".to_string();

        let mut material = TemplateMaterial::new(
            canvas.id.clone(), // 使用素材的真实ID
            String::new(),     // template_id 稍后设置
            String::new(),     // 画布素材没有 local_material_id
            name,
            TemplateMaterialType::Canvas,
            String::new(),     // 画布素材没有文件路径
        );

        // 将画布属性存储为元数据
        let metadata = serde_json::json!({
            "color": canvas.color,
            "image": canvas.image,
            "type": canvas.material_type
        });
        material.metadata = Some(metadata.to_string());

        Ok(material)
    }

    /// 解析轨道
    fn parse_track(
        track_raw: &TrackRaw,
        template_id: &str,
        track_index: u32,
        material_map: &HashMap<String, String>,
        warnings: &mut Vec<String>,
    ) -> Result<Track> {
        let track_type = match track_raw.track_type.as_str() {
            "video" => TrackType::Video,
            "audio" => TrackType::Audio,
            "text" => TrackType::Text,
            "sticker" => TrackType::Sticker,
            "effect" => TrackType::Effect,
            other => TrackType::Other(other.to_string()),
        };

        let track_name = format!("轨道{} ({})", track_index + 1, track_raw.track_type);
        let mut track = Track::new(
            track_raw.id.clone(), // 使用轨道的真实ID
            template_id.to_string(),
            track_name,
            track_type,
            track_index,
        );

        // 解析轨道片段
        for (segment_index, segment_raw) in track_raw.segments.iter().enumerate() {
            match Self::parse_segment(
                segment_raw,
                &track.id,
                segment_index as u32,
                material_map,
            ) {
                Ok(segment) => track.add_segment(segment),
                Err(e) => warnings.push(format!(
                    "轨道片段解析失败 {}: {}",
                    segment_raw.id,
                    e
                )),
            }
        }

        Ok(track)
    }

    /// 解析轨道片段
    fn parse_segment(
        segment_raw: &SegmentRaw,
        track_id: &str,
        segment_index: u32,
        material_map: &HashMap<String, String>,
    ) -> Result<TrackSegment> {
        // 使用 target_timerange 作为时间轴位置（这是片段在最终视频中的位置）
        let start_time = segment_raw.target_timerange.start;
        let target_duration = segment_raw.target_timerange.duration;
        let end_time = start_time + target_duration;

        // 播放速度不影响片段在时间轴上的时长
        // target_duration 就是片段的实际时长
        let speed = segment_raw.speed.unwrap_or(1.0);

        let segment_name = format!("片段{}", segment_index + 1);
        let mut segment = TrackSegment::new(
            segment_raw.id.clone(), // 使用片段的真实ID
            track_id.to_string(),
            segment_name,
            start_time,
            end_time,
            segment_index,
        );

        // 保持时间轴上的时长，不要覆盖为 actual_duration
        // segment.duration 应该是 end_time - start_time (时间轴时长)
        // actual_duration 存储在 properties 中供前端使用

        // 关联素材
        if let Some(material_id) = material_map.get(&segment_raw.material_id) {
            segment.associate_material(material_id.clone());
        }

        // 存储原始属性信息
        let properties = serde_json::json!({
            "original_material_id": segment_raw.material_id,
            "target_timerange": segment_raw.target_timerange,
            "source_timerange": segment_raw.source_timerange,
            "speed": segment_raw.speed,
            "visible": segment_raw.visible,
            "volume": segment_raw.volume,
            "speed_info": {
                "is_speed_modified": speed != 1.0,
                "speed_value": speed,
                "speed_description": if speed > 1.0 { "加速播放" } else if speed < 1.0 { "减速播放" } else { "正常播放" }
            }
        });
        segment.properties = Some(properties.to_string());

        Ok(segment)
    }

    /// 验证解析结果
    pub fn validate_result(result: &ParseResult) -> Vec<String> {
        let mut errors = Vec::new();

        // 检查模板基本信息
        if result.template.name.is_empty() {
            errors.push("模板名称不能为空".to_string());
        }

        if result.template.duration == 0 {
            errors.push("模板时长不能为0".to_string());
        }

        if result.template.fps <= 0.0 {
            errors.push("帧率必须大于0".to_string());
        }

        // 检查画布配置
        if result.template.canvas_config.width == 0 || result.template.canvas_config.height == 0 {
            errors.push("画布尺寸不能为0".to_string());
        }

        // 检查素材
        if result.template.materials.is_empty() {
            errors.push("模板必须包含至少一个素材".to_string());
        }

        // 缺失文件只作为警告，不阻止导入
        // 注释掉这部分，让缺失文件不影响导入
        // if !result.missing_files.is_empty() {
        //     errors.push(format!(
        //         "发现{}个缺失文件，可能影响模板使用",
        //         result.missing_files.len()
        //     ));
        // }

        errors
    }
}
