#!/usr/bin/env python3
"""
视频处理器
"""

import os
import uuid
import hashlib
from abc import ABC, abstractmethod
from typing import List
from datetime import datetime
from pathlib import Path

from .types import VideoSegment
from python_core.config import settings
from python_core.utils.logger import logger

class VideoProcessor(ABC):
    """视频处理器接口"""

    @abstractmethod
    def split_video(self, video_path: str, scene_changes: List[float], 
                   original_video_id: str, tags: List[str] = None) -> List[VideoSegment]:
        """分割视频"""
        pass

    @abstractmethod
    def generate_thumbnail(self, video_path: str, timestamp: float, output_path: str) -> bool:
        """生成缩略图"""
        pass

    @abstractmethod
    def calculate_hash(self, file_path: str) -> str:
        """计算文件哈希"""
        pass

class OpenCVVideoProcessor(VideoProcessor):
    """使用OpenCV的视频处理器"""

    def __init__(self):
        self.segments_dir = settings.temp_dir / "video_segments"
        self.segments_dir.mkdir(parents=True, exist_ok=True)

    def split_video(self, video_path: str, scene_changes: List[float], 
                   original_video_id: str, tags: List[str] = None) -> List[VideoSegment]:
        """分割视频"""
        if tags is None:
            tags = []

        # 为分镜片段处理标签
        segment_tags = [tag for tag in tags if tag != "原始"]
        if "分镜" not in segment_tags:
            segment_tags.append("分镜")

        try:
            import cv2
        except ImportError:
            logger.warning("OpenCV not available, creating single segment")
            return self._create_single_segment(video_path, original_video_id, segment_tags)

        return self._create_multiple_segments(video_path, scene_changes, original_video_id, segment_tags)

    def _create_single_segment(self, video_path: str, original_video_id: str, tags: List[str]) -> List[VideoSegment]:
        """创建单个片段"""
        import shutil

        segment_id = str(uuid.uuid4())
        segment_filename = f"{segment_id}.mp4"
        segment_path = self.segments_dir / segment_filename

        # 复制整个视频作为单个片段
        shutil.copy2(video_path, segment_path)

        # 获取基本信息
        file_size = segment_path.stat().st_size
        now = datetime.now().isoformat()

        segment = VideoSegment(
            id=segment_id,
            original_video_id=original_video_id,
            segment_index=0,
            filename=segment_filename,
            file_path=str(segment_path),
            md5_hash=self.calculate_hash(str(segment_path)),
            file_size=file_size,
            duration=0.0,  # 需要从视频信息获取
            width=0,
            height=0,
            fps=0.0,
            format='mp4',
            start_time=0.0,
            end_time=0.0,
            tags=tags.copy(),
            use_count=0,
            created_at=now,
            updated_at=now
        )

        return [segment]

    def _create_multiple_segments(self, video_path: str, scene_changes: List[float],
                                original_video_id: str, tags: List[str]) -> List[VideoSegment]:
        """创建多个片段"""
        try:
            import cv2
        except ImportError:
            return self._create_single_segment(video_path, original_video_id, tags)

        segments = []

        try:
            cap = cv2.VideoCapture(video_path)
            fps = cap.get(cv2.CAP_PROP_FPS)
            width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

            if fps <= 0:
                cap.release()
                return self._create_single_segment(video_path, original_video_id, tags)

            fourcc = cv2.VideoWriter_fourcc(*'mp4v')

            for i in range(len(scene_changes) - 1):
                start_time = scene_changes[i]
                end_time = scene_changes[i + 1]
                duration = end_time - start_time

                # 跳过太短的片段
                if duration < 1.0:
                    continue

                segment_id = str(uuid.uuid4())
                segment_filename = f"{segment_id}.mp4"
                segment_path = self.segments_dir / segment_filename

                # 创建视频写入器
                out = cv2.VideoWriter(str(segment_path), fourcc, fps, (width, height))

                # 跳转到开始帧
                start_frame = int(start_time * fps)
                end_frame = int(end_time * fps)

                cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)

                frame_count = 0
                target_frames = end_frame - start_frame

                while frame_count < target_frames:
                    ret, frame = cap.read()
                    if not ret:
                        break

                    out.write(frame)
                    frame_count += 1

                out.release()

                # 检查文件是否创建成功
                if not segment_path.exists() or segment_path.stat().st_size == 0:
                    logger.error(f"Failed to create segment: {segment_path}")
                    continue

                # 创建片段记录
                now = datetime.now().isoformat()

                segment = VideoSegment(
                    id=segment_id,
                    original_video_id=original_video_id,
                    segment_index=i,
                    filename=segment_filename,
                    file_path=str(segment_path),
                    md5_hash=self.calculate_hash(str(segment_path)),
                    file_size=segment_path.stat().st_size,
                    duration=duration,
                    width=width,
                    height=height,
                    fps=fps,
                    format='mp4',
                    start_time=start_time,
                    end_time=end_time,
                    tags=tags.copy(),
                    use_count=0,
                    created_at=now,
                    updated_at=now
                )

                segments.append(segment)
                logger.info(f"Created segment {i}: {start_time:.2f}s - {end_time:.2f}s")

            cap.release()
            logger.info(f"Successfully created {len(segments)} video segments")

        except Exception as e:
            logger.error(f"Failed to create multiple segments: {e}")
            return self._create_single_segment(video_path, original_video_id, tags)

        return segments

    def generate_thumbnail(self, video_path: str, timestamp: float, output_path: str) -> bool:
        """生成视频缩略图"""
        try:
            import cv2
        except ImportError:
            return False

        try:
            cap = cv2.VideoCapture(video_path)
            fps = cap.get(cv2.CAP_PROP_FPS)

            if fps <= 0:
                cap.release()
                return False

            # 跳转到指定时间
            frame_number = int(timestamp * fps)
            cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)

            ret, frame = cap.read()
            cap.release()

            if ret:
                success = cv2.imwrite(output_path, frame)
                logger.info(f"Thumbnail generated: {output_path}")
                return success
            else:
                logger.error(f"Failed to read frame at {timestamp}s")
                return False

        except Exception as e:
            logger.error(f"Failed to generate thumbnail: {e}")
            return False

    def calculate_hash(self, file_path: str) -> str:
        """计算文件MD5哈希值"""
        try:
            hash_md5 = hashlib.md5()
            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"Failed to calculate MD5 hash: {e}")
            return ""

def create_video_processor() -> VideoProcessor:
    """创建视频处理器"""
    try:
        return OpenCVVideoProcessor()
    except Exception:
        raise Exception("No video processor available")
