"""
Evaluate Workflow.

评估工作流：针对视频的筛选
流程：查询原视频信息 → 评估筛选视频 → 更新数据库
"""

from typing import Dict, Any, Optional
import json
from langgraph.graph import StateGraph, END

from src.components.agents.base import BaseGraphAgent
from src.components.agents.evaluate_agent import EvaluateAgent
from src.models import get_db, DecodeVideo, EvaluateRecord, EvaluateStatus
from src.utils.logger import get_logger
from utils.general import get_now_ts

logger = get_logger(__name__)


class EvaluateWorkflow(BaseGraphAgent):
    """评估工作流

    功能：
    - 针对视频的筛选
    - 流程：查询原视频信息 → 评估筛选视频 → 更新数据库
    - 管理状态传递

    实现方式：BaseGraphAgent (LangGraph)
    """

    def __init__(
        self,
        name: str = "evaluate_workflow",
        description: str = "评估工作流 - 针对视频的筛选",
        model_provider: str = "google_genai"
    ):
        super().__init__(
            name=name,
            description=description,
            state_class=dict
        )

        self.model_provider = model_provider

        # 初始化评估Agent
        self.evaluate_agent = EvaluateAgent(
            model_provider=model_provider
        )

    def _build_graph(self) -> StateGraph:
        """构建工作流图
        
        流程：
        1. 查询原视频信息（根据task_id查询decode_videos表）
        2. 更新评估状态为执行中（根据evaluate_id更新evaluate_record表status为1）
        3. 评估筛选视频（使用evaluate_agent）
        4. 更新数据库（根据evaluate_id更新evaluate_record表）
        """
        workflow = StateGraph(dict)

        # 添加节点
        workflow.add_node("query_original_video", self._query_original_video_node)
        workflow.add_node("update_evaluate_status", self._update_evaluate_status_node)
        workflow.add_node("evaluate_videos", self._evaluate_videos_node)
        workflow.add_node("update_database", self._update_database_node)

        # 设置入口点
        workflow.set_entry_point("query_original_video")

        # 添加边
        workflow.add_edge("query_original_video", "update_evaluate_status")
        workflow.add_edge("update_evaluate_status", "evaluate_videos")
        workflow.add_edge("evaluate_videos", "update_database")
        workflow.add_edge("update_database", END)

        logger.info("评估工作流图构建完成 - 流程：查询原视频信息 → 更新评估状态 → 评估筛选视频 → 更新数据库")

        return workflow

    def _query_original_video_node(self, state: Dict[str, Any]) -> Dict[str, Any]:
        """节点：查询原视频信息
        
        根据task_id查询decode_videos表，获取原视频的标题和解构内容
        
        Args:
            state: 状态字典，包含：
                - task_id: 任务ID
                - evaluate_id: 评估ID
                
        Returns:
            更新后的状态，包含：
                - original_video_title: 原视频标题
                - original_video_content: 原视频解构内容
        """
        logger.info("=== 执行节点：查询原视频信息 ===")

        try:
            task_id = state.get("task_id")
            if not task_id:
                logger.error("task_id为空，无法查询原视频信息")
                state["workflow_error"] = "task_id为空"
                return state

            # 查询数据库
            db = next(get_db())
            try:
                decode_video = db.query(DecodeVideo).filter_by(task_id=task_id).first()
                
                if not decode_video:
                    logger.error(f"未找到task_id={task_id}的解构记录")
                    state["workflow_error"] = f"未找到task_id={task_id}的解构记录"
                    return state

                # 提取标题（从result或decode_result_v2中提取）
                title = ""
                original_content = {}

                # 优先使用decode_result_v2（ScriptWorkflowV2的结果）
                if decode_video.decode_result_v2:
                    try:
                        decode_result_v2 = json.loads(decode_video.decode_result_v2)
                        original_content["decode_result_v2"] = decode_result_v2
                        # 尝试从结果中提取标题
                        if isinstance(decode_result_v2, dict):
                            # 尝试多种可能的路径
                            title = (
                                decode_result_v2.get("视频信息", {}).get("标题", "") or
                                decode_result_v2.get("title", "") or
                                decode_result_v2.get("视频标题", "") or
                                ""
                            )
                    except json.JSONDecodeError as e:
                        logger.warning(f"解析decode_result_v2失败: {e}")

                # 使用result（原有结果）
                if decode_video.result:
                    try:
                        result = json.loads(decode_video.result)
                        original_content["result"] = result
                        # 如果还没有标题，尝试从result中提取
                        if not title and isinstance(result, dict):
                            title = (
                                result.get("视频信息", {}).get("标题", "") or
                                result.get("title", "") or
                                result.get("视频标题", "") or
                                ""
                            )
                    except json.JSONDecodeError as e:
                        logger.warning(f"解析result失败: {e}")

                # 如果还是没有标题，使用video_id作为标题
                if not title and decode_video.video_id:
                    title = f"视频 {decode_video.video_id}"

                logger.info(f"查询到原视频信息: task_id={task_id}, title={title}")

                # 更新状态
                state["original_video_title"] = title
                state["original_video_content"] = original_content

            finally:
                db.close()

        except Exception as e:
            logger.error(f"查询原视频信息失败: {e}", exc_info=True)
            state["workflow_error"] = f"查询原视频信息失败: {str(e)}"

        return state

    def _update_evaluate_status_node(self, state: Dict[str, Any]) -> Dict[str, Any]:
        """节点：更新评估状态为执行中
        
        根据evaluate_id更新evaluate_record表中的status为1（EXECUTING）
        
        Args:
            state: 状态字典，包含：
                - evaluate_id: 评估ID
                
        Returns:
            更新后的状态
        """
        logger.info("=== 执行节点：更新评估状态为执行中 ===")

        try:
            evaluate_id = state.get("evaluate_id")
            if not evaluate_id:
                logger.warning("evaluate_id为空，跳过状态更新")
                return state

            db = next(get_db())
            try:
                evaluate_record = db.query(EvaluateRecord).filter_by(evaluate_id=evaluate_id).first()
                if evaluate_record:
                    evaluate_record.update_status(EvaluateStatus.EXECUTING)
                    db.commit()
                    logger.info(f"更新评估记录状态为执行中: evaluate_id={evaluate_id}")
                else:
                    logger.warning(f"未找到evaluate_id={evaluate_id}的评估记录")
            finally:
                db.close()

        except Exception as e:
            logger.error(f"更新评估状态失败: {e}", exc_info=True)
            # 状态更新失败不影响工作流继续执行
            state["status_update_error"] = f"更新评估状态失败: {str(e)}"

        return state

    def _evaluate_videos_node(self, state: Dict[str, Any]) -> Dict[str, Any]:
        """节点：评估筛选视频
        
        使用evaluate_agent从视频列表中筛选出和原视频最匹配的内容
        
        Args:
            state: 状态字典，包含：
                - original_video_title: 原视频标题
                - original_video_content: 原视频解构内容
                - search_result: 待评估的视频列表
                
        Returns:
            更新后的状态，包含：
                - evaluate_result: 评估结果列表
        """
        logger.info("=== 执行节点：评估筛选视频 ===")

        try:
            # 检查是否有错误
            if state.get("workflow_error"):
                logger.warning("存在错误，跳过评估步骤")
                return state

            # 初始化Agent
            if not self.evaluate_agent.is_initialized:
                self.evaluate_agent.initialize()

            # 执行评估
            evaluate_result = self.evaluate_agent.process(state)

            # 更新状态
            state.update(evaluate_result)

            logger.info("视频评估完成")

        except Exception as e:
            logger.error(f"评估筛选视频失败: {e}", exc_info=True)
            state["workflow_error"] = f"评估筛选视频失败: {str(e)}"
            # 即使失败，也设置一个空的评估结果
            state["evaluate_result"] = []

        return state

    def _update_database_node(self, state: Dict[str, Any]) -> Dict[str, Any]:
        """节点：更新数据库
        
        根据evaluate_id更新evaluate_record表中的evaluate_result、status和updated_at
        
        Args:
            state: 状态字典，包含：
                - evaluate_id: 评估ID
                - evaluate_result: 评估结果列表
                
        Returns:
            更新后的状态
        """
        logger.info("=== 执行节点：更新数据库 ===")

        try:
            evaluate_id = state.get("evaluate_id")
            if not evaluate_id:
                logger.error("evaluate_id为空，无法更新数据库")
                state["workflow_error"] = "evaluate_id为空"
                return state

            evaluate_result = state.get("evaluate_result", [])

            # 将评估结果转换为JSON字符串
            result_json = json.dumps(evaluate_result, ensure_ascii=False, indent=2)

            # 更新数据库
            db = next(get_db())
            try:
                evaluate_record = db.query(EvaluateRecord).filter_by(evaluate_id=evaluate_id).first()
                
                if not evaluate_record:
                    logger.error(f"未找到evaluate_id={evaluate_id}的评估记录")
                    state["workflow_error"] = f"未找到evaluate_id={evaluate_id}的评估记录"
                    return state

                # 更新评估结果
                evaluate_record.evaluate_result = result_json

                # 更新状态
                if state.get("workflow_error"):
                    evaluate_record.update_status(EvaluateStatus.FAILED)
                else:
                    evaluate_record.update_status(EvaluateStatus.SUCCESS)

                # 更新updated_at（通过SQL的onupdate自动更新，但也可以手动设置）
                from sqlalchemy.sql import func
                evaluate_record.updated_at = func.now()

                db.commit()

                logger.info(f"数据库更新成功: evaluate_id={evaluate_id}")

            finally:
                db.close()

        except Exception as e:
            logger.error(f"更新数据库失败: {e}", exc_info=True)
            state["workflow_error"] = f"更新数据库失败: {str(e)}"
            
            # 尝试更新数据库状态为失败
            try:
                evaluate_id = state.get("evaluate_id")
                if evaluate_id:
                    db = next(get_db())
                    try:
                        evaluate_record = db.query(EvaluateRecord).filter_by(evaluate_id=evaluate_id).first()
                        if evaluate_record:
                            evaluate_record.update_status(EvaluateStatus.FAILED)
                            db.commit()
                    finally:
                        db.close()
            except Exception as db_error:
                logger.error(f"更新数据库状态为失败时出错: {db_error}", exc_info=True)

        return state

    def invoke(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
        """执行工作流（公共接口）
        
        Args:
            input_data: 输入数据，包含：
                - task_id: 任务ID（必需）
                - evaluate_id: 评估ID（必需）
                - search_result: 待评估的视频列表（必需）
                
        Returns:
            执行结果，包含：
                - evaluate_result: 评估结果列表
                - workflow_status: 工作流状态（success/failed）
        """
        logger.info("=== 开始执行评估工作流 ===")
        logger.info(f"input_data keys: {list(input_data.keys())}")

        # 确保工作流已初始化
        if not self.is_initialized:
            self.initialize()

        # 验证输入参数
        task_id = input_data.get("task_id")
        evaluate_id = input_data.get("evaluate_id")
        search_result = input_data.get("search_result", [])

        if not task_id:
            error_msg = "未提供task_id，无法执行工作流"
            logger.error(error_msg)
            return {
                "error": error_msg,
                "workflow_status": "failed",
                "input_data": input_data
            }

        if not evaluate_id:
            error_msg = "未提供evaluate_id，无法执行工作流"
            logger.error(error_msg)
            return {
                "error": error_msg,
                "workflow_status": "failed",
                "input_data": input_data
            }

        if not search_result:
            error_msg = "未提供search_result，无法执行工作流"
            logger.error(error_msg)
            return {
                "error": error_msg,
                "workflow_status": "failed",
                "input_data": input_data
            }

        # 初始化状态
        initial_state = {
            "task_id": task_id,
            "evaluate_id": evaluate_id,
            "search_result": search_result,
        }

        # 执行工作流
        result = None
        try:
            result = self.compiled_graph.invoke(initial_state)
        except Exception as e:
            error_msg = f"工作流执行异常: {str(e)}"
            logger.error(error_msg, exc_info=True)
            # 更新数据库记录为失败状态
            if result is None:
                result = initial_state
            result["workflow_error"] = error_msg
            # 触发更新数据库节点以更新状态
            try:
                self._update_database_node(result)
            except Exception as db_error:
                logger.error(f"更新数据库状态为失败时出错: {db_error}", exc_info=True)
            return {
                "status": 3,
                "error": error_msg,
                "workflow_status": "failed",
                "exception_type": type(e).__name__
            }

        # 检查是否有错误
        if result.get("workflow_error"):
            logger.error(f"工作流执行失败: {result.get('workflow_error')}")
            return {
                "status": 3,
                "error": result.get("workflow_error"),
                "workflow_status": "failed",
                "evaluate_result": result.get("evaluate_result", [])
            }

        logger.info("=== 评估工作流执行完成 ===")
        return {
            "status": 2,
            "workflow_status": "success",
            "evaluate_result": result.get("evaluate_result", [])
        }

