"""
Review Task Manager

审核任务管理器 - 负责管理过程中审核和生成后审核任务
"""
import uuid
from typing import List, Optional, Dict, Any, AsyncIterator
from datetime import datetime, timedelta
from pydantic import ValidationError

from app.models.review_task import (
    ReviewTask,
    ReviewTaskStatus,
    ReviewMode,
    ReviewAction,
    ProcessReviewRequest,
    UserReviewActionRequest,
    PostCreationReviewRequest,
    PostCreationReviewResult,
    ReviewTaskLocation,
    ReviewTriggerSource
)
from app.models.review import ReviewConfig, DimensionType, DimensionConfig, CustomRule
from app.core.review.review_manager import ReviewManager
from app.utils.logger import get_logger


logger = get_logger(__name__)


# ============================================
# 内存存储（过程审核任务自动销毁，不需要持久化）
# ============================================

_process_tasks: Dict[str, ReviewTask] = {}


class ReviewTaskManager:
    """
    审核任务管理器

    职责：
    1. 管理过程中审核任务（内存存储，自动销毁）
    2. 管理生成后审核任务（持久化到项目）
    3. 处理用户对审核任务的响应
    4. 调用ReviewManager执行审核
    """

    def __init__(self, review_manager: Optional[ReviewManager] = None):
        self.review_manager = review_manager

        if not self.review_manager:
            from app.core.review.review_manager import get_review_manager
            self.review_manager = get_review_manager()

        logger.info("审核任务管理器初始化完成")

    # ============================================
    # 过程中审核（内存存储，自动销毁）
    # ============================================

    async def create_process_review_task(
        self,
        request: ProcessReviewRequest
    ) -> ReviewTask:
        """
        创建过程中审核任务

        过程中审核任务存储在内存中，用户确认后自动销毁。

        Args:
            request: 审核请求

        Returns:
            ReviewTask: 创建的审核任务
        """
        task_id = str(uuid.uuid4())

        # 根据触发来源确定可用操作
        if request.trigger_source == ReviewTriggerSource.AGENT_AUTO:
            # Agent自主推送的审核：确认继续、补充信息、拒绝
            available_actions = [
                ReviewAction.CONFIRM,
                ReviewAction.MODIFY,
                ReviewAction.OTHER
            ]
        else:
            # 其他来源：标准操作
            available_actions = [
                ReviewAction.CONFIRM,
                ReviewAction.IGNORE
            ]

        task = ReviewTask(
            id=task_id,
            project_id=request.project_id,
            mode=ReviewMode.PROCESS,
            trigger_source=request.trigger_source,
            issue_type=request.issue_type,
            issue_description=request.issue_description,
            severity=request.severity,
            location=request.location,
            review_config_id=request.review_config_id,
            skill_id=request.skill_id,
            rule_id=request.rule_id,
            available_actions=available_actions,
            status=ReviewTaskStatus.AWAITING_USER,
            suggestion=request.suggestion,
            context_data={
                "trigger_source": request.trigger_source.value,
                "skill_id": request.skill_id,
                "rule_id": request.rule_id
            }
        )

        # 存储到内存
        _process_tasks[task_id] = task

        logger.info(
            f"创建过程中审核任务: {task_id}, "
            f"问题: {request.issue_type}, 严重度: {request.severity}"
        )

        return task

    async def handle_user_review_action(
        self,
        request: UserReviewActionRequest
    ) -> ReviewTask:
        """
        处理用户对审核任务的响应

        Args:
            request: 用户操作请求

        Returns:
            ReviewTask: 更新后的任务
        """
        task = _process_tasks.get(request.task_id)

        if not task:
            logger.warning(f"审核任务不存在: {request.task_id}")
            raise ValueError(f"审核任务不存在: {request.task_id}")

        # 验证操作是否可用
        if request.action not in task.available_actions:
            logger.warning(
                f"操作 {request.action} 对任务 {request.task_id} 不可用, "
                f"可用操作: {[a.value for a in task.available_actions]}"
            )
            raise ValueError(f"操作不可用")

        # 更新任务状态
        if request.action == ReviewAction.CONFIRM:
            task.status = ReviewTaskStatus.COMPLETED
            task.user_response = "用户确认继续"
            task.completed_at = datetime.now()

        elif request.action == ReviewAction.MODIFY:
            task.status = ReviewTaskStatus.MODIFIED
            task.user_response = request.user_response or "用户修改了内容"
            task.completed_at = datetime.now()
            # 保存修改后的内容到上下文
            if request.modified_content:
                task.context_data = task.context_data or {}
                task.context_data["modified_content"] = request.modified_content

        elif request.action == ReviewAction.OTHER:
            task.status = ReviewTaskStatus.COMPLETED
            task.user_response = request.user_response or "用户补充了信息"
            task.completed_at = datetime.now()

        elif request.action == ReviewAction.IGNORE:
            task.status = ReviewTaskStatus.IGNORED
            task.user_response = "用户忽略问题"
            task.completed_at = datetime.now()

        logger.info(
            f"处理用户操作: {request.action.value}, "
            f"任务: {task_id}, 新状态: {task.status.value}"
        )

        # 从内存中移除已完成/忽略的任务
        if task.status in [ReviewTaskStatus.COMPLETED, ReviewTaskStatus.IGNORED]:
            _process_tasks.pop(request.task_id, None)
            logger.info(f"过程审核任务已销毁: {request.task_id}")

        return task

    def get_pending_process_tasks(
        self,
        project_id: str
    ) -> List[ReviewTask]:
        """
        获取项目所有待处理的过程审核任务

        Args:
            project_id: 项目ID

        Returns:
            List[ReviewTask]: 待处理任务列表
        """
        return [
            task for task in _process_tasks.values()
            if task.project_id == project_id and
            task.status == ReviewTaskStatus.AWAITING_USER
        ]

    # ============================================
    # 生成后审核（持久化到项目）
    # ============================================

    async def execute_post_creation_review(
        self,
        request: PostCreationReviewRequest,
        project_config: ReviewConfig
    ) -> PostCreationReviewResult:
        """
        执行生成后审核

        根据用户配置的规则/Skill进行自动检查，根据阈值报告问题。

        Args:
            request: 生成后审核请求
            project_config: 项目审核配置

        Returns:
            PostCreationReviewResult: 审核结果
        """
        from app.models.project import SeriesProject, Episode

        # TODO: 从项目获取剧集
        # 这里简化处理，实际需要从episode_repo获取
        episode = Episode(
            projectId=request.project_id,
            id=request.episode_id,
            number=1,
            content="",
            status="completed"
        )
        project = SeriesProject(
            id=request.project_id,
            name="",
            globalContext=None
        )

        tasks = []
        high_severity_count = 0

        # 1. 使用配置的Skill进行审核
        if request.use_configured_skills and project_config.enabled_review_skills:
            for skill_id in project_config.enabled_review_skills:
                skill_tasks = await self._execute_skill_review(
                    project=project,
                    episode=episode,
                    skill_id=skill_id,
                    project_config=project_config
                )
                tasks.extend(skill_tasks)
                high_severity_count += sum(1 for t in skill_tasks if t.severity == "high")

        # 2. 使用配置的规则进行审核
        if request.use_configured_rules and project_config.custom_rules:
            for rule in project_config.custom_rules:
                if rule.enabled:
                    rule_tasks = await self._execute_rule_review(
                        project=project,
                        episode=episode,
                        rule=rule,
                        project_config=project_config
                    )
                    tasks.extend(rule_tasks)
                    high_severity_count += sum(1 for t in rule_tasks if t.severity == "high")

        # 3. 根据阈值判断是否通过
        pass_threshold = request.pass_threshold or project_config.pass_threshold
        passed = high_severity_count == 0

        # 4. 生成总体分数
        if tasks:
            overall_score = max(0, 100 - len(tasks) * 5 - high_severity_count * 10)
        else:
            overall_score = 100.0

        result = PostCreationReviewResult(
            task_count=len(tasks),
            passed=passed,
            tasks=tasks,
            overall_score=overall_score
        )

        logger.info(
            f"生成后审核完成: {request.project_id}, "
            f"任务数: {len(tasks)}, 高严重度: {high_severity_count}, "
            f"通过: {passed}, 分数: {overall_score}"
        )

        return result

    async def _execute_skill_review(
        self,
        project,
        episode,
        skill_id: str,
        project_config: ReviewConfig
    ) -> List[ReviewTask]:
        """
        执行Skill审核

        Args:
            project: 项目
            episode: 剧集
            skill_id: Skill ID
            project_config: 审核配置

        Returns:
            List[ReviewTask]: 发现的审核任务
        """
        tasks = []

        try:
            # 获取Skill信息
            from app.core.skills.skill_manager import get_skill_manager
            skill_manager = get_skill_manager()
            skill = skill_manager.get_skill_by_id(skill_id)

            if not skill:
                logger.warning(f"Skill不存在: {skill_id}")
                return tasks

            # 使用ReviewManager的LLM审核
            from app.models.review import Issue, IssueType, SeverityLevel, Location

            issues = await self.review_manager._run_llm_review(
                project=project,
                episode=episode,
                dimension=DimensionType.custom,  # 使用custom维度代表Skill审核
                strictness=0.7
            )

            # 转换为ReviewTask
            for issue in issues:
                task = ReviewTask(
                    id=str(uuid.uuid4()),
                    project_id=project.id,
                    episode_id=episode.id,
                    mode=ReviewMode.POST_CREATION,
                    trigger_source=ReviewTriggerSource.USER_CONFIGURED_SKILL,
                    issue_type=issue.type.value,
                    issue_description=issue.description,
                    severity=issue.severity.value,
                    location=ReviewTaskLocation(
                        episode_number=issue.location.episode,
                        scene_number=issue.location.scene,
                        line_number=issue.location.line,
                        content_snippet=issue.location.context
                    ),
                    skill_id=skill_id,
                    available_actions=[ReviewAction.CONFIRM, ReviewAction.IGNORE, ReviewAction.MODIFY],
                    status=ReviewTaskStatus.AWAITING_USER,
                    suggestion=issue.suggestion
                )
                tasks.append(task)

            return tasks

        except Exception as e:
            logger.error(f"Skill审核失败 {skill_id}: {str(e)}")
            return tasks

    async def _execute_rule_review(
        self,
        project,
        episode,
        rule,
        project_config: ReviewConfig
    ) -> List[ReviewTask]:
        """
        执行规则审核

        Args:
            project: 项目
            episode: 剧集
            rule: 自定义规则
            project_config: 审核配置

        Returns:
            List[ReviewTask]: 发现的审核任务
        """
        tasks = []

        try:
            # 调用ReviewManager的规则检查
            issues = await self.review_manager._check_single_rule(
                episode=episode,
                rule=rule,
                config=project_config
            )

            # 转换为ReviewTask
            for issue in issues:
                task = ReviewTask(
                    id=str(uuid.uuid4()),
                    project_id=project.id,
                    episode_id=episode.id,
                    mode=ReviewMode.POST_CREATION,
                    trigger_source=ReviewTriggerSource.USER_CONFIGURED_RULE,
                    issue_type=issue.type.value,
                    issue_description=issue.description,
                    severity=issue.severity.value,
                    location=ReviewTaskLocation(
                        episode_number=issue.location.episode,
                        scene_number=issue.location.scene,
                        line_number=issue.location.line,
                        content_snippet=issue.location.context
                    ),
                    rule_id=rule.id,
                    available_actions=[ReviewAction.CONFIRM, ReviewAction.IGNORE, ReviewAction.MODIFY],
                    status=ReviewTaskStatus.AWAITING_USER,
                    suggestion=issue.suggestion
                )
                tasks.append(task)

            return tasks

        except Exception as e:
            logger.error(f"规则审核失败 {rule.id}: {str(e)}")
            return tasks

    def get_process_task_by_id(
        self,
        task_id: str
    ) -> Optional[ReviewTask]:
        """获取过程中审核任务"""
        return _process_tasks.get(task_id)

    def cleanup_expired_tasks(self):
        """清理已过期的任务（超过24小时未处理）"""
        now = datetime.now()
        expired_ids = []

        for task_id, task in _process_tasks.items():
            if task.status == ReviewTaskStatus.AWAITING_USER:
                # 检查是否创建超过24小时
                if (now - task.created_at).total_seconds() > 86400:
                    expired_ids.append(task_id)

        for task_id in expired_ids:
            _process_tasks.pop(task_id, None)
            logger.info(f"清理过期审核任务: {task_id}")

        if expired_ids:
            return len(expired_ids)
        return 0

    async def create_task_from_review(
        self,
        project_id: str,
        episode_number: int,
        review_data: Dict[str, Any]
    ) -> ReviewTask:
        """
        从审查结果创建审核任务

        当 Agent 完成剧集审查后，将审查结果转换为审核任务并推送到审核系统。

        Args:
            project_id: 项目ID
            episode_number: 剧集号
            review_data: 审查数据，包含 score, passed, issue_count, issues 等信息

        Returns:
            ReviewTask: 创建的审核任务
        """
        task_id = str(uuid.uuid4())

        # 根据 issue_count 判断是否创建任务
        issue_count = review_data.get("issue_count", 0)
        issues = review_data.get("issues", [])

        # 创建任务位置信息
        location = ReviewTaskLocation(
            episode_number=episode_number,
            scene_number=None,
            line_number=None,
            content_snippet=f"EP{episode_number} 审查发现 {issue_count} 个问题"
        )

        # 如果有问题，创建待处理的审核任务
        if issue_count > 0:
            # 找出最高严重度的问题
            high_severity_issues = [i for i in issues if i.get("severity") == "high"]
            medium_severity_issues = [i for i in issues if i.get("severity") == "medium"]

            # 确定总体严重度
            if high_severity_issues:
                severity = "high"
            elif medium_severity_issues:
                severity = "medium"
            else:
                severity = "low"

            # 构建问题描述
            issue_types = set(i.get("dimension", "unknown") for i in issues)
            issue_description = f"EP{episode_number} 审查发现 {issue_count} 个问题，涉及维度: {', '.join(issue_types)}"

            # 列出主要问题
            main_issues = []
            for issue in issues[:5]:  # 只列出前5个
                main_issues.append(f"• [{issue.get('dimension', 'unknown')}] {issue.get('description', '')[:50]}")

            if main_issues:
                issue_description += "\n主要问题:\n" + "\n".join(main_issues)

            # 创建审核任务
            task = ReviewTask(
                id=task_id,
                project_id=project_id,
                episode_id=f"ep_{episode_number}",  # 剧集ID（简化）
                mode=ReviewMode.POST_CREATION,
                trigger_source=ReviewTriggerSource.USER_CONFIGURED_RULE,  # Agent主动审查
                issue_type="episode_review",
                issue_description=issue_description,
                severity=severity,
                location=location,
                available_actions=[
                    ReviewAction.CONFIRM,  # 确认问题
                    ReviewAction.MODIFY,    # 修改内容
                    ReviewAction.IGNORE     # 忽略问题
                ],
                status=ReviewTaskStatus.AWAITING_USER,
                suggestion=f"建议检查并修复 EP{episode_number} 中发现的问题",
                context_data={
                    "episode_number": episode_number,
                    "episode_title": review_data.get("episode_title", ""),
                    "score": review_data.get("score", 0),
                    "issue_count": issue_count,
                    "issues": issues,
                    "trigger_source": "agent_review",
                    "created_at": datetime.now().isoformat()
                }
            )

            # 存储到内存（生成后审核任务）
            _process_tasks[task_id] = task

            logger.info(
                f"从审查结果创建审核任务: {task_id}, "
                f"EP{episode_number}, 问题数: {issue_count}, 严重度: {severity}"
            )

            return task
        else:
            # 没有问题，返回一个已确认的任务表示审查通过
            task = ReviewTask(
                id=task_id,
                project_id=project_id,
                episode_id=f"ep_{episode_number}",
                mode=ReviewMode.POST_CREATION,
                trigger_source=ReviewTriggerSource.USER_CONFIGURED_RULE,
                issue_type="episode_review",
                issue_description=f"EP{episode_number} 审查通过，未发现问题",
                severity="low",
                location=location,
                available_actions=[ReviewAction.CONFIRM],
                status=ReviewTaskStatus.COMPLETED,  # 直接标记为已完成
                context_data={
                    "episode_number": episode_number,
                    "episode_title": review_data.get("episode_title", ""),
                    "score": review_data.get("score", 100),
                    "issue_count": 0,
                    "trigger_source": "agent_review",
                    "created_at": datetime.now().isoformat()
                }
            )

            logger.info(f"EP{episode_number} 审查通过，无问题")

            return task


# ============================================
# 流式审核助手 - 支持Agent在生成过程中推送审核
# ============================================

class StreamReviewHelper:
    """
    流式审核助手

    帮助Agent在流式输出过程中推送审核任务。
    提供阻塞式等待用户确认的机制。
    """

    def __init__(self, project_id: str, task_manager: ReviewTaskManager):
        self.project_id = project_id
        self.task_manager = task_manager
        self.pending_tasks: List[str] = []
        self.user_responses: Dict[str, str] = {}

    async def push_review_task(
        self,
        issue_type: str,
        issue_description: str,
        severity: str = "medium",
        location: Optional[ReviewTaskLocation] = None,
        skill_id: Optional[str] = None,
        suggestion: Optional[str] = None
    ) -> ReviewTask:
        """
        推送审核任务（由Agent调用）

        阻塞式等待用户确认后才能继续。

        Args:
            issue_type: 问题类型
            issue_description: 问题描述
            severity: 严重程度
            location: 位置信息
            skill_id: 使用的Skill ID
            suggestion: 修改建议

        Returns:
            ReviewTask: 创建的审核任务
        """
        request = ProcessReviewRequest(
            project_id=self.project_id,
            issue_type=issue_type,
            issue_description=issue_description,
            severity=severity,
            location=location or ReviewTaskLocation(),
            trigger_source=ReviewTriggerSource.AGENT_AUTO,
            skill_id=skill_id,
            suggestion=suggestion
        )

        task = await self.task_manager.create_process_review_task(request)
        self.pending_tasks.append(task.id)

        logger.info(f"Agent推送审核任务: {task.id}")

        return task

    async def wait_for_user_response(
        self,
        task_id: str,
        timeout: int = 300  # 5分钟超时
    ) -> Optional[str]:
        """
        等待用户响应（阻塞式）

        Args:
            task_id: 任务ID
            timeout: 超时时间（秒）

        Returns:
            Optional[str]: 用户响应内容，超时返回None
        """
        # 检查用户是否已响应
        if task_id in self.user_responses:
            return self.user_responses[task_id]

        # 这里简化处理 - 实际应该通过WebSocket通知前端并等待响应
        # 返回None表示等待中
        return None

    def record_user_response(self, task_id: str, response: str):
        """记录用户响应"""
        self.user_responses[task_id] = response
        if task_id in self.pending_tasks:
            self.pending_tasks.remove(task_id)
        logger.info(f"用户响应已记录: {task_id}, 响应: {response}")

    def has_pending_tasks(self) -> bool:
        """是否有待处理的审核任务"""
        return len(self.pending_tasks) > 0


# ============================================
# 全局单例
# ============================================

_review_task_manager: Optional[ReviewTaskManager] = None


def get_review_task_manager() -> ReviewTaskManager:
    """获取审核任务管理器单例"""
    global _review_task_manager
    if _review_task_manager is None:
        _review_task_manager = ReviewTaskManager()
    return _review_task_manager


review_task_manager = get_review_task_manager()
