#!/usr/bin/env python3
"""
Batch Workflow Nodes
批量工作流节点
"""

import time
from pathlib import Path
from typing import Dict, Any
from concurrent.futures import ThreadPoolExecutor, as_completed

from python_core.utils.logger import logger
from python_core.utils.jsonrpc_enhanced import ProgressLevel
from ..types.batch_workflow_state import BatchSceneDetectionWorkflowState, BatchVideoTask
from ..types.enums import DetectorType, OutputFormat
from ..services.detector_service import SceneDetectorService
from ..services.video_info_service import VideoInfoService
from ..services.ai_analysis_service import AIAnalysisService
from python_core.services.ffmpeg_slice_service_sync import FfmpegSliceService, SliceOptions, SliceSegment
from ..utils.result_saver import ResultSaver


class BatchWorkflowNodes:
    """批量工作流节点"""
    
    def __init__(self):
        # 初始化服务
        self.detector_service = SceneDetectorService()
        self.video_info_service = VideoInfoService()
        self.ai_analysis_service = AIAnalysisService()
        self.splitter_service = FfmpegSliceService()
        self.result_saver = ResultSaver()
    
    def validate_batch_input(self, state: BatchSceneDetectionWorkflowState) -> Dict[str, Any]:
        """验证批量输入"""
        state.current_stage = "validation"
        state.send_progress("validate_input", "验证批量输入参数", ProgressLevel.INFO)
        
        errors = []
        
        # 检查视频文件
        valid_videos = []
        for video_path in state.video_paths:
            if not video_path.exists():
                errors.append(f"视频文件不存在: {video_path}")
                continue
            
            if video_path.suffix.lower() not in {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm', '.m4v'}:
                errors.append(f"不支持的视频格式: {video_path}")
                continue
            
            valid_videos.append(video_path)
        
        if not valid_videos:
            errors.append("没有有效的视频文件")
        
        # 检查输出目录
        if state.output_base_dir:
            try:
                state.output_base_dir.mkdir(parents=True, exist_ok=True)
            except Exception as e:
                errors.append(f"无法创建输出目录: {e}")
        
        # 检查FFmpeg（如果需要切分）
        if state.enable_video_splitting:
            if not self.splitter_service.check_ffmpeg_available():
                errors.append("FFmpeg不可用，无法进行视频切分")
        
        if errors:
            state.global_errors.extend(errors)
            return {
                "workflow_state": "failed",
                "errors": errors,
                "valid_videos": valid_videos
            }
        
        # 更新有效视频列表
        state.video_paths = valid_videos
        state.tasks = [
            BatchVideoTask(
                video_path=video_path,
                output_dir=state.output_base_dir / video_path.stem if state.output_base_dir else None
            )
            for video_path in valid_videos
        ]
        state.total_tasks = len(state.tasks)
        
        state.send_progress("validate_input", f"验证完成，找到 {len(valid_videos)} 个有效视频", ProgressLevel.SUCCESS)
        
        return {
            "workflow_state": "validated",
            "valid_videos": valid_videos,
            "total_tasks": state.total_tasks
        }
    
    def process_videos_batch(self, state: BatchSceneDetectionWorkflowState) -> Dict[str, Any]:
        """批量处理视频"""
        state.current_stage = "batch_processing"
        state.send_progress("batch_process", "开始批量处理视频", ProgressLevel.INFO)
        
        # 使用线程池进行并发处理
        with ThreadPoolExecutor(max_workers=state.max_concurrent) as executor:
            # 提交所有任务
            future_to_index = {}
            for i, task in enumerate(state.tasks):
                future = executor.submit(self._process_single_video, state, i, task)
                future_to_index[future] = i
            
            # 处理完成的任务
            for future in as_completed(future_to_index):
                task_index = future_to_index[future]
                try:
                    result = future.result()
                    if result["success"]:
                        state.mark_task_completed(
                            task_index, 
                            result["detection_result"], 
                            result.get("split_results", [])
                        )
                        state.send_progress(
                            "task_completed", 
                            f"任务 {task_index + 1}/{state.total_tasks} 完成: {state.tasks[task_index].video_path.name}",
                            ProgressLevel.SUCCESS,
                            {"task_index": task_index + 1, "video_name": state.tasks[task_index].video_path.name}
                        )
                    else:
                        state.mark_task_failed(task_index, result["error"])
                        state.send_progress(
                            "task_failed", 
                            f"任务 {task_index + 1}/{state.total_tasks} 失败: {result['error']}",
                            ProgressLevel.ERROR,
                            {"task_index": task_index + 1, "error": result["error"]}
                        )
                except Exception as e:
                    state.mark_task_failed(task_index, str(e))
                    state.send_progress(
                        "task_error", 
                        f"任务 {task_index + 1}/{state.total_tasks} 异常: {str(e)}",
                        ProgressLevel.ERROR,
                        {"task_index": task_index + 1, "error": str(e)}
                    )
        
        # 生成批量处理结果
        summary = state.get_summary()
        
        state.send_progress(
            "batch_complete", 
            f"批量处理完成: {state.completed_tasks}/{state.total_tasks} 成功",
            ProgressLevel.SUCCESS,
            summary
        )
        
        return {
            "workflow_state": "completed",
            "summary": summary,
            "completed_tasks": state.completed_tasks,
            "failed_tasks": state.failed_tasks,
            "total_tasks": state.total_tasks
        }
    
    def _process_single_video(self, state: BatchSceneDetectionWorkflowState, 
                             task_index: int, task: BatchVideoTask) -> Dict[str, Any]:
        """处理单个视频"""
        try:
            task.status = "processing"
            task.start_time = time.time()
            
            logger.info(f"🎬 处理视频 {task_index + 1}/{state.total_tasks}: {task.video_path.name}")
            
            # 1. 场景检测
            detection_result = self.detector_service.detect_scenes(
                task.video_path,
                DetectorType(state.detector_type),
                state.threshold,
                state.min_scene_length
            )
            
            if not detection_result.success:
                return {
                    "success": False,
                    "error": f"场景检测失败: {detection_result.error}"
                }
            
            # 2. 保存检测结果
            if task.output_dir:
                task.output_dir.mkdir(parents=True, exist_ok=True)
                result_file = task.output_dir / f"scenes.{state.output_format}"
                self.result_saver.save_results(
                    detection_result, 
                    result_file, 
                    OutputFormat(state.output_format)
                )
            
            # 3. 视频切分（如果启用）
            split_results = []
            if state.enable_video_splitting and task.output_dir:
                try:
                    # 创建切分选项
                    slice_options = SliceOptions(
                        crf=state.split_quality,
                        preset=state.split_preset
                    )

                    # 转换场景为SliceSegment
                    segments = [
                        SliceSegment(start=scene.start_time, end=scene.end_time)
                        for scene in detection_result.scenes
                    ]

                    # 创建输出目录
                    scenes_dir = task.output_dir / "scenes"
                    scenes_dir.mkdir(parents=True, exist_ok=True)

                    # 生成输出路径
                    base_output_path = str(scenes_dir / f"{task.video_path.stem}_scene")

                    # 使用同步方法进行切分
                    # 检查是否无场景，如果是则跳过切分
                    if len(segments) <= 0:
                        logger.info(f"🔄 检测到 0 个场景切换，跳过切分，直接使用源文件")
                        # 创建输出目录
                        scenes_dir.mkdir(parents=True, exist_ok=True)

                        # 直接复制源文件作为结果
                        import shutil
                        source_file = task.video_path
                        target_file = scenes_dir / f"{task.video_path.stem}_scene_001.mp4"

                        try:
                            shutil.copy2(source_file, target_file)
                            logger.info(f"✅ 源文件已复制到: {target_file}")

                            # 获取源文件元数据
                            metadata = self.splitter_service.get_video_metadata(str(source_file))

                            # 创建模拟的切分结果
                            slice_results = [(str(target_file), metadata)]

                            # 修正场景统计：无场景切换 = 1个场景（整个视频）
                            detection_result.total_scenes = 1

                        except Exception as e:
                            logger.error(f"❌ 复制源文件失败: {e}")
                            slice_results = []
                    else:
                        logger.info(f"🎬 检测到 {len(segments)} 个场景，开始切分")
                        slice_results = self.splitter_service.slice_video(
                            media_path=str(task.video_path),
                            segments=segments,
                            options=slice_options,
                            output_path=base_output_path
                        )

                    # 转换为兼容格式
                    split_results_raw = []

                    # 创建一个简单的结果对象
                    class SplitResult:
                        def __init__(self, scene_index, output_path, start_time, end_time, duration, file_size, success, error=None):
                            self.scene_index = scene_index
                            self.output_path = Path(output_path)
                            self.start_time = start_time
                            self.end_time = end_time
                            self.duration = duration
                            self.file_size = file_size
                            self.success = success
                            self.error = error

                    for i, (output_path, metadata) in enumerate(slice_results):
                        if len(detection_result.scenes) == 0:
                            # 无场景切换的情况：整个视频作为一个场景
                            split_result = SplitResult(
                                scene_index=0,
                                output_path=output_path,
                                start_time=0.0,
                                end_time=metadata.duration,
                                duration=metadata.duration,
                                file_size=metadata.size,
                                success=Path(output_path).exists(),
                                error=None if Path(output_path).exists() else "文件不存在"
                            )
                            split_results_raw.append(split_result)
                        else:
                            # 有场景切换的情况
                            scene = detection_result.scenes[i] if i < len(detection_result.scenes) else None
                            if scene:
                                split_result = SplitResult(
                                    scene_index=i,
                                    output_path=output_path,
                                    start_time=scene.start_time,
                                    end_time=scene.end_time,
                                    duration=scene.duration,
                                    file_size=metadata.size,
                                    success=Path(output_path).exists(),
                                    error=None if Path(output_path).exists() else "文件不存在"
                                )
                                split_results_raw.append(split_result)
                    
                    
                    # 创建切分摘要
                    successful_results = [r for r in split_results_raw if r.success]
                    failed_results = [r for r in split_results_raw if not r.success]

                    split_summary = {
                        "video_path": str(task.video_path),
                        "total_scenes": len(split_results_raw),
                        "successful_splits": len(successful_results),
                        "failed_splits": len(failed_results),
                        "success_rate": len(successful_results) / len(split_results_raw) * 100 if split_results_raw else 0,
                        "total_output_size": sum(r.file_size for r in successful_results)
                    }
                    summary_file = task.output_dir / "split_summary.json"
                    import json
                    with open(summary_file, 'w', encoding='utf-8') as f:
                        json.dump(split_summary, f, indent=2, ensure_ascii=False)
                    
                except Exception as e:
                    logger.error(f"视频切分失败: {e}")
                    # 切分失败不影响整体任务成功
            
            # 4. 添加视频时长检查，如果时长大于 最大视频时长 那么就要进行二次切分 确保 视频不大于 最大视频时长
            final_split_results = []

            for split_result in split_results_raw:
                try:
                    # 检查切分后的视频时长
                    video_path = str(split_result.output_path)

                    if split_result.duration > state.max_video_duration:
                        logger.info(f"⚠️ 片段 {split_result.scene_index + 1} 时长 {split_result.duration:.2f}s 超过限制 {state.max_video_duration:.2f}s，进行二次切分")

                        # 进行二次切分
                        secondary_results = self.splitter_service.check_and_split_by_duration(
                            video_path=video_path,
                            max_duration=state.max_video_duration,
                            options=slice_options,
                            output_dir=str(split_result.output_path.parent)
                        )

                        # 处理二次切分结果
                        for i, (secondary_path, secondary_metadata) in enumerate(secondary_results):
                            if len(secondary_results) > 1:
                                # 如果进行了二次切分，创建新的结果对象
                                secondary_split_result = SplitResult(
                                    scene_index=split_result.scene_index,
                                    output_path=secondary_path,
                                    start_time=split_result.start_time + (i * state.max_video_duration),
                                    end_time=min(split_result.start_time + ((i + 1) * state.max_video_duration), split_result.end_time),
                                    duration=secondary_metadata.duration,
                                    file_size=secondary_metadata.size,
                                    success=Path(secondary_path).exists(),
                                    error=None if Path(secondary_path).exists() else "二次切分文件不存在"
                                )
                                final_split_results.append(secondary_split_result)

                                # 删除原始的过长片段（如果二次切分成功）
                                if Path(video_path).exists() and len(secondary_results) > 1:
                                    try:
                                        Path(video_path).unlink()
                                        logger.info(f"🗑️ 已删除过长的原始片段: {Path(video_path).name}")
                                    except Exception as e:
                                        logger.warning(f"⚠️ 删除原始片段失败: {e}")
                            else:
                                # 如果没有进行二次切分（时长检查通过），保持原结果
                                final_split_results.append(split_result)
                    else:
                        # 时长未超过限制，直接添加到最终结果
                        final_split_results.append(split_result)

                except Exception as e:
                    logger.error(f"❌ 处理片段 {split_result.scene_index + 1} 的时长检查时出错: {e}")
                    # 出错时保持原结果
                    final_split_results.append(split_result)

            # 使用最终的切分结果
            split_results_raw = final_split_results

            # 转换为字典格式
            split_results = [
                {
                    "scene_index": r.scene_index + 1,
                    "output_path": str(r.output_path),
                    "start_time": r.start_time,
                    "end_time": r.end_time,
                    "duration": r.duration,
                    "file_size": r.file_size,
                    "success": r.success,
                    "error": r.error
                }
                for r in split_results_raw
            ]
            
            # 更新统计信息
            logger.info(f"📊 最终生成 {len(split_results_raw)} 个视频片段（包含二次切分）")
            
            task.end_time = time.time()
            
            return {
                "success": True,
                "detection_result": detection_result,
                "split_results": split_results
            }
            
        except Exception as e:
            task.end_time = time.time()
            return {
                "success": False,
                "error": str(e)
            }
