"""
视频录制模块

支持浏览器操作视频录制，提供：
- 自动录制（通过配置启用）
- 手动控制录制
- 视频管理（获取、保存、删除）
"""
import asyncio
import time
from pathlib import Path
from typing import Optional, List, Dict, Any, TYPE_CHECKING
from dataclasses import dataclass, field
from datetime import datetime
from loguru import logger

if TYPE_CHECKING:
    from playwright.async_api import Page, Video, BrowserContext


@dataclass
class VideoInfo:
    """视频信息"""
    path: str
    page_url: str
    start_time: datetime
    end_time: Optional[datetime] = None
    duration_seconds: float = 0.0
    size_bytes: int = 0
    tab_name: Optional[str] = None


@dataclass
class VideoRecord:
    """视频录制记录"""
    video: Any  # Playwright Video 对象
    page: Any  # Page 对象
    start_time: datetime
    tab_name: str
    saved_path: Optional[str] = None


class VideoManager:
    """
    视频管理器

    管理浏览器视频录制。

    Example:
        async with EasyBrowser(record_video=True) as browser:
            video = browser.video

            # 获取当前页面视频
            video_path = await video.get_current_video()

            # 保存所有视频
            await video.save_all()

            # 获取视频列表
            videos = video.list_videos()
    """

    def __init__(
        self,
        context: "BrowserContext",
        video_dir: str = "./videos",
        video_size: Optional[Dict[str, int]] = None,
    ):
        self._context = context
        self._video_dir = Path(video_dir)
        self._video_size = video_size
        self._records: Dict[str, VideoRecord] = {}
        self._videos: List[VideoInfo] = []
        self._paused_pages: set = set()

    def register_page(self, page: "Page", tab_name: str) -> None:
        """
        注册页面以跟踪视频

        Args:
            page: 页面对象
            tab_name: 标签页名称
        """
        video = page.video
        if video:
            self._records[tab_name] = VideoRecord(
                video=video,
                page=page,
                start_time=datetime.now(),
                tab_name=tab_name,
            )
            logger.debug(f"注册视频录制: {tab_name}")

    def unregister_page(self, tab_name: str) -> None:
        """取消注册页面"""
        self._records.pop(tab_name, None)

    async def get_video(self, tab_name: str) -> Optional[str]:
        """
        获取指定标签页的视频路径

        Args:
            tab_name: 标签页名称

        Returns:
            str: 视频文件路径，如果不存在返回 None
        """
        record = self._records.get(tab_name)
        if record and record.video:
            try:
                path = await record.video.path()
                return path
            except Exception as e:
                logger.warning(f"获取视频路径失败: {e}")
        return None

    async def save_video(
        self,
        tab_name: str,
        save_path: Optional[str] = None,
    ) -> Optional[str]:
        """
        保存指定标签页的视频

        Args:
            tab_name: 标签页名称
            save_path: 保存路径（可选）

        Returns:
            str: 保存的视频路径
        """
        record = self._records.get(tab_name)
        if not record or not record.video:
            logger.warning(f"未找到视频记录: {tab_name}")
            return None

        try:
            # 确保目录存在
            self._video_dir.mkdir(parents=True, exist_ok=True)

            # 获取原始视频路径
            original_path = await record.video.path()

            if save_path:
                target_path = Path(save_path)
            else:
                # 自动生成文件名
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                filename = f"{tab_name}_{timestamp}.webm"
                target_path = self._video_dir / filename

            # 复制视频文件
            import shutil
            shutil.copy2(original_path, target_path)

            record.saved_path = str(target_path)
            logger.info(f"视频已保存: {target_path}")

            return str(target_path)

        except Exception as e:
            logger.error(f"保存视频失败: {e}")
            return None

    async def save_all(self, clear_records: bool = False) -> List[str]:
        """
        保存所有视频

        Args:
            clear_records: 是否清除记录

        Returns:
            List[str]: 保存的视频路径列表
        """
        saved_paths = []

        for tab_name in list(self._records.keys()):
            path = await self.save_video(tab_name)
            if path:
                saved_paths.append(path)

        if clear_records:
            self._records.clear()

        logger.info(f"已保存 {len(saved_paths)} 个视频")
        return saved_paths

    async def delete_video(self, tab_name: str) -> bool:
        """
        删除指定标签页的视频

        Args:
            tab_name: 标签页名称

        Returns:
            bool: 是否成功
        """
        record = self._records.get(tab_name)
        if not record:
            return False

        try:
            if record.video:
                path = await record.video.path()
                if path and Path(path).exists():
                    Path(path).unlink()
                    logger.info(f"视频已删除: {path}")

            self._records.pop(tab_name, None)
            return True

        except Exception as e:
            logger.error(f"删除视频失败: {e}")
            return False

    def list_videos(self) -> List[VideoInfo]:
        """
        列出所有视频信息

        Returns:
            List[VideoInfo]: 视频信息列表
        """
        videos = []

        for tab_name, record in self._records.items():
            info = VideoInfo(
                path=record.saved_path or "",
                page_url=record.page.url if record.page else "",
                start_time=record.start_time,
                tab_name=tab_name,
            )
            videos.append(info)

        return videos

    def get_video_count(self) -> int:
        """获取视频数量"""
        return len(self._records)

    async def get_total_size(self) -> int:
        """获取所有视频总大小（字节）"""
        total_size = 0

        for record in self._records.values():
            try:
                if record.video:
                    path = await record.video.path()
                    if path and Path(path).exists():
                        total_size += Path(path).stat().st_size
            except:
                pass

        return total_size

    def clear_records(self) -> None:
        """清除所有记录（不删除文件）"""
        self._records.clear()

    async def pause_recording(self, tab_name: str) -> bool:
        """
        暂停录制（通过隐藏页面实现）

        注意：Playwright 不原生支持暂停，此方法通过标记实现。

        Args:
            tab_name: 标签页名称

        Returns:
            bool: 是否成功
        """
        if tab_name in self._records:
            self._paused_pages.add(tab_name)
            logger.debug(f"视频录制已暂停: {tab_name}")
            return True
        return False

    async def resume_recording(self, tab_name: str) -> bool:
        """
        恢复录制

        Args:
            tab_name: 标签页名称

        Returns:
            bool: 是否成功
        """
        if tab_name in self._paused_pages:
            self._paused_pages.discard(tab_name)
            logger.debug(f"视频录制已恢复: {tab_name}")
            return True
        return False

    def is_recording(self, tab_name: str) -> bool:
        """检查是否正在录制"""
        return tab_name in self._records and tab_name not in self._paused_pages


class VideoRecorder:
    """
    视频录制器

    提供更细粒度的视频录制控制。

    Example:
        recorder = VideoRecorder(browser)

        # 开始录制当前页面
        await recorder.start()

        # ... 执行操作 ...

        # 停止录制并保存
        video_path = await recorder.stop("my_video.webm")
    """

    def __init__(self, browser):
        self._browser = browser
        self._recording = False
        self._start_time: Optional[datetime] = None
        self._video_path: Optional[str] = None

    async def start(self, name: Optional[str] = None) -> bool:
        """
        开始录制

        注意：视频录制通常在浏览器启动时配置。
        此方法主要用于标记录制开始时间。

        Args:
            name: 录制名称

        Returns:
            bool: 是否成功
        """
        if self._recording:
            logger.warning("已经在录制中")
            return False

        self._recording = True
        self._start_time = datetime.now()
        self._name = name or f"video_{self._start_time.strftime('%Y%m%d_%H%M%S')}"

        logger.info(f"视频录制已开始: {self._name}")
        return True

    async def stop(self, save_path: Optional[str] = None) -> Optional[str]:
        """
        停止录制并保存

        Args:
            save_path: 保存路径

        Returns:
            str: 视频路径
        """
        if not self._recording:
            logger.warning("未在录制中")
            return None

        self._recording = False

        # 获取并保存视频
        if hasattr(self._browser, 'video') and self._browser.video:
            video_path = await self._browser.video.save_video(
                self._browser._current_tab,
                save_path,
            )
            self._video_path = video_path

            duration = (datetime.now() - self._start_time).total_seconds() if self._start_time else 0
            logger.info(f"视频录制已停止: {video_path}, 时长: {duration:.1f}s")

            return video_path

        return None

    def is_recording(self) -> bool:
        """是否正在录制"""
        return self._recording

    def get_elapsed_time(self) -> float:
        """获取已录制时长（秒）"""
        if self._recording and self._start_time:
            return (datetime.now() - self._start_time).total_seconds()
        return 0.0
