"""
项目素材管理服务
"""

import json
import hashlib
from pathlib import Path
from typing import List, Dict, Any, Optional
from datetime import datetime

from python_core.utils.logger import logger


class ProjectMaterialService:
    """项目素材管理服务"""
    
    def __init__(self):
        logger.info("ProjectMaterialService 初始化完成")
    
    def import_video_materials(
        self,
        video_segments: List[Any],
        project_id: str,
        project_directory: Path,
        source_video_path: str,
        material_tags: Optional[List[str]] = None
    ) -> Dict[str, Any]:
        """
        导入视频素材到项目
        
        Args:
            video_segments: 视频片段列表
            project_id: 项目ID
            project_directory: 项目目录
            source_video_path: 源视频路径
            material_tags: 素材标签
            
        Returns:
            Dict: 导入结果
        """
        
        try:
            # 创建项目素材目录
            uncategorized_dir = project_directory / "未分类文件夹"
            uncategorized_dir.mkdir(parents=True, exist_ok=True)
            
            # 加载现有的项目素材列表
            material_list_file = project_directory / "project_material.json"
            existing_materials = self._load_material_list(material_list_file)
            
            # 处理视频片段
            new_materials = []
            imported_count = 0
            skipped_count = 0
            
            for segment in video_segments:
                if not segment.success:
                    continue
                
                try:
                    result = self._import_single_segment(
                        segment=segment,
                        uncategorized_dir=uncategorized_dir,
                        existing_materials=existing_materials,
                        project_id=project_id,
                        source_video_path=source_video_path,
                        material_tags=material_tags or []
                    )
                    
                    if result["imported"]:
                        new_materials.append(result["material_info"])
                        imported_count += 1
                        logger.info(f"✅ 素材已导入: {result['original_filename']} -> {result['target_filename']}")
                    else:
                        skipped_count += 1
                        logger.info(f"📋 素材已存在，跳过: {result['original_filename']}")
                        
                except Exception as e:
                    logger.error(f"❌ 导入素材失败 {segment.output_path.name}: {e}")
                    skipped_count += 1
            
            # 更新项目素材列表
            if new_materials:
                existing_materials.extend(new_materials)
                self._save_material_list(material_list_file, existing_materials)
                logger.info(f"📝 项目素材列表已更新: 新增 {len(new_materials)} 个素材")
            
            return {
                "success": True,
                "imported_count": imported_count,
                "skipped_count": skipped_count,
                "total_count": len(video_segments),
                "new_materials": new_materials
            }
            
        except Exception as e:
            logger.error(f"❌ 项目素材导入失败: {e}")
            return {
                "success": False,
                "error": str(e),
                "imported_count": 0,
                "skipped_count": 0,
                "total_count": len(video_segments)
            }
    
    def _import_single_segment(
        self,
        segment: Any,
        uncategorized_dir: Path,
        existing_materials: List[Dict],
        project_id: str,
        source_video_path: str,
        material_tags: List[str]
    ) -> Dict[str, Any]:
        """导入单个视频片段"""
        
        # 复制文件到项目目录
        import shutil
        temp_target_path = uncategorized_dir / f"temp_{segment.output_path.name}"
        shutil.copy2(segment.output_path, temp_target_path)
        
        # 计算复制后文件的MD5
        file_md5 = self._calculate_file_md5(temp_target_path)
        
        # 检查是否已存在相同MD5的素材
        if any(material.get('md5') == file_md5 for material in existing_materials):
            # 删除临时文件
            temp_target_path.unlink()
            return {
                "imported": False,
                "original_filename": segment.output_path.name,
                "reason": "duplicate_md5"
            }
        
        # 重命名为最终文件名
        target_filename = f"{file_md5}.mp4"
        target_path = uncategorized_dir / target_filename
        temp_target_path.rename(target_path)
        
        # 创建素材信息
        material_info = {
            "id": file_md5,
            "md5": file_md5,
            "original_filename": segment.output_path.name,
            "filename": target_filename,
            "file_path": str(target_path),
            "relative_path": f"未分类文件夹/{target_filename}",
            "file_size": segment.file_size,
            "duration": segment.duration,
            "start_time": segment.start_time,
            "end_time": segment.end_time,
            "scene_index": segment.scene_index,
            "tags": material_tags.copy(),
            "created_at": datetime.now().isoformat(),
            "use_count": 0,
            "source_video": source_video_path,
            "project_id": project_id
        }
        
        return {
            "imported": True,
            "material_info": material_info,
            "original_filename": segment.output_path.name,
            "target_filename": target_filename
        }
    
    def _load_material_list(self, material_list_file: Path) -> List[Dict]:
        """加载项目素材列表"""
        if not material_list_file.exists():
            return []
        
        try:
            with open(material_list_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception as e:
            logger.warning(f"⚠️ 读取现有素材列表失败: {e}")
            return []
    
    def _save_material_list(self, material_list_file: Path, materials: List[Dict]):
        """保存项目素材列表"""
        try:
            with open(material_list_file, 'w', encoding='utf-8') as f:
                json.dump(materials, f, ensure_ascii=False, indent=2)
        except Exception as e:
            logger.error(f"❌ 保存项目素材列表失败: {e}")
            raise
    
    def _calculate_file_md5(self, file_path: Path) -> str:
        """计算文件MD5值"""
        hash_md5 = hashlib.md5()
        try:
            with open(file_path, "rb") as f:
                for chunk in iter(lambda: f.read(4096), b""):
                    hash_md5.update(chunk)
            return hash_md5.hexdigest()
        except Exception as e:
            logger.error(f"❌ 计算MD5失败 {file_path}: {e}")
            # 如果计算MD5失败，使用文件名和大小作为备用标识
            return hashlib.md5(f"{file_path.name}_{file_path.stat().st_size}".encode()).hexdigest()
    
    def get_project_materials(self, project_directory: Path) -> List[Dict]:
        """获取项目素材列表"""
        material_list_file = project_directory / "project_material.json"
        return self._load_material_list(material_list_file)
    
    def add_material_tags(self, project_directory: Path, material_id: str, tags: List[str]) -> bool:
        """为素材添加标签"""
        try:
            material_list_file = project_directory / "project_material.json"
            materials = self._load_material_list(material_list_file)
            
            for material in materials:
                if material.get('id') == material_id:
                    existing_tags = set(material.get('tags', []))
                    new_tags = existing_tags.union(set(tags))
                    material['tags'] = list(new_tags)
                    
                    self._save_material_list(material_list_file, materials)
                    logger.info(f"✅ 素材标签已更新: {material_id}")
                    return True
            
            logger.warning(f"⚠️ 未找到素材: {material_id}")
            return False
            
        except Exception as e:
            logger.error(f"❌ 添加素材标签失败: {e}")
            return False
    
    def remove_material(self, project_directory: Path, material_id: str) -> bool:
        """删除项目素材"""
        try:
            material_list_file = project_directory / "project_material.json"
            materials = self._load_material_list(material_list_file)
            
            # 查找要删除的素材
            material_to_remove = None
            for i, material in enumerate(materials):
                if material.get('id') == material_id:
                    material_to_remove = materials.pop(i)
                    break
            
            if material_to_remove:
                # 删除文件
                file_path = Path(material_to_remove['file_path'])
                if file_path.exists():
                    file_path.unlink()
                    logger.info(f"🗑️ 已删除素材文件: {file_path.name}")
                
                # 更新素材列表
                self._save_material_list(material_list_file, materials)
                logger.info(f"✅ 素材已删除: {material_id}")
                return True
            else:
                logger.warning(f"⚠️ 未找到素材: {material_id}")
                return False
                
        except Exception as e:
            logger.error(f"❌ 删除素材失败: {e}")
            return False
    
    def get_material_stats(self, project_directory: Path) -> Dict[str, Any]:
        """获取项目素材统计信息"""
        try:
            materials = self.get_project_materials(project_directory)
            
            total_count = len(materials)
            total_size = sum(material.get('file_size', 0) for material in materials)
            total_duration = sum(material.get('duration', 0) for material in materials)
            
            # 按标签统计
            tag_stats = {}
            for material in materials:
                for tag in material.get('tags', []):
                    tag_stats[tag] = tag_stats.get(tag, 0) + 1
            
            # 按使用次数统计
            used_count = sum(1 for material in materials if material.get('use_count', 0) > 0)
            unused_count = total_count - used_count
            
            return {
                "total_count": total_count,
                "total_size": total_size,
                "total_duration": total_duration,
                "used_count": used_count,
                "unused_count": unused_count,
                "tag_stats": tag_stats
            }
            
        except Exception as e:
            logger.error(f"❌ 获取素材统计失败: {e}")
            return {
                "total_count": 0,
                "total_size": 0,
                "total_duration": 0,
                "used_count": 0,
                "unused_count": 0,
                "tag_stats": {}
            }
