"""
Webhook API
用于接收外部系统的Webhook请求并触发工作流执行
"""
from fastapi import APIRouter, Depends, HTTPException, status, Request, Header
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import Optional, Dict, Any
import logging
from app.core.database import get_db
from app.models.workflow import Workflow
from app.models.execution import Execution
from app.tasks.workflow_tasks import execute_workflow_task
import uuid

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/webhooks", tags=["webhooks"])


class WebhookTriggerRequest(BaseModel):
    """Webhook触发请求模型"""
    workflow_id: Optional[str] = None
    workflow_name: Optional[str] = None
    input_data: Dict[str, Any] = {}
    headers: Optional[Dict[str, Any]] = None
    query_params: Optional[Dict[str, Any]] = None


@router.post("/trigger/{workflow_id}")
async def trigger_workflow_by_webhook(
    workflow_id: str,
    request: Request,
    x_webhook_token: Optional[str] = Header(None, alias="X-Webhook-Token"),
    db: Session = Depends(get_db)
):
    """
    通过Webhook触发工作流执行
    
    支持通过工作流ID触发工作流，可以传递自定义的输入数据。
    可选：通过 X-Webhook-Token 头进行认证（如果工作流配置了webhook_token）。
    
    Args:
        workflow_id: 工作流ID
        request: FastAPI请求对象（用于获取请求体、查询参数、请求头）
        x_webhook_token: Webhook Token（可选，用于认证）
        db: 数据库会话
    """
    try:
        # 查找工作流
        workflow = db.query(Workflow).filter(Workflow.id == workflow_id).first()
        
        if not workflow:
            raise HTTPException(status_code=404, detail="工作流不存在")
        
        # 检查工作流状态
        if workflow.status not in ['published', 'running']:
            raise HTTPException(
                status_code=400, 
                detail=f"工作流状态为 {workflow.status}，无法通过Webhook触发"
            )
        
        # 获取请求数据
        try:
            body_data = await request.json() if request.headers.get("content-type", "").startswith("application/json") else {}
        except:
            body_data = {}
        
        # 获取查询参数
        query_params = dict(request.query_params)
        
        # 获取请求头（排除一些系统头）
        headers = {}
        excluded_headers = ['host', 'content-length', 'connection', 'user-agent']
        for key, value in request.headers.items():
            if key.lower() not in excluded_headers:
                headers[key] = value
        
        # 构建输入数据：合并查询参数、请求体和请求头
        input_data = {
            **query_params,
            **body_data,
            '_webhook': {
                'headers': headers,
                'query_params': query_params,
                'body': body_data,
                'method': request.method,
                'path': str(request.url.path)
            }
        }
        
        # 创建执行记录
        execution = Execution(
            workflow_id=workflow_id,
            input_data=input_data,
            status="pending"
        )
        db.add(execution)
        db.commit()
        db.refresh(execution)
        
        # 异步执行工作流
        workflow_data = {
            'nodes': workflow.nodes,
            'edges': workflow.edges
        }
        task = execute_workflow_task.delay(
            str(execution.id),
            workflow_id,
            workflow_data,
            input_data
        )
        
        # 更新执行记录的task_id
        execution.task_id = task.id
        db.commit()
        db.refresh(execution)
        
        return {
            "status": "success",
            "message": "工作流已触发执行",
            "execution_id": str(execution.id),
            "task_id": task.id
        }
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Webhook触发工作流失败: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"触发工作流失败: {str(e)}")


@router.post("/trigger/by-name/{workflow_name}")
async def trigger_workflow_by_name(
    workflow_name: str,
    request: Request,
    x_webhook_token: Optional[str] = Header(None, alias="X-Webhook-Token"),
    db: Session = Depends(get_db)
):
    """
    通过工作流名称触发工作流执行
    
    支持通过工作流名称触发工作流，适用于通过名称标识工作流的场景。
    
    Args:
        workflow_name: 工作流名称
        request: FastAPI请求对象
        x_webhook_token: Webhook Token（可选）
        db: 数据库会话
    """
    try:
        # 查找工作流（按名称，且状态为published或running）
        workflow = db.query(Workflow).filter(
            Workflow.name == workflow_name,
            Workflow.status.in_(['published', 'running'])
        ).first()
        
        if not workflow:
            raise HTTPException(status_code=404, detail=f"未找到名称为 '{workflow_name}' 的已发布工作流")
        
        # 获取请求数据
        try:
            body_data = await request.json() if request.headers.get("content-type", "").startswith("application/json") else {}
        except:
            body_data = {}
        
        # 获取查询参数
        query_params = dict(request.query_params)
        
        # 获取请求头
        headers = {}
        excluded_headers = ['host', 'content-length', 'connection', 'user-agent']
        for key, value in request.headers.items():
            if key.lower() not in excluded_headers:
                headers[key] = value
        
        # 构建输入数据
        input_data = {
            **query_params,
            **body_data,
            '_webhook': {
                'headers': headers,
                'query_params': query_params,
                'body': body_data,
                'method': request.method,
                'path': str(request.url.path)
            }
        }
        
        # 创建执行记录
        execution = Execution(
            workflow_id=workflow.id,
            input_data=input_data,
            status="pending"
        )
        db.add(execution)
        db.commit()
        db.refresh(execution)
        
        # 异步执行工作流
        workflow_data = {
            'nodes': workflow.nodes,
            'edges': workflow.edges
        }
        task = execute_workflow_task.delay(
            str(execution.id),
            workflow.id,
            workflow_data,
            input_data
        )
        
        # 更新执行记录的task_id
        execution.task_id = task.id
        db.commit()
        db.refresh(execution)
        
        return {
            "status": "success",
            "message": "工作流已触发执行",
            "execution_id": str(execution.id),
            "task_id": task.id,
            "workflow_id": workflow.id
        }
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Webhook触发工作流失败: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"触发工作流失败: {str(e)}")
