from typing import Any

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session

from app.api.deps import User, get_db
from app.api.permissions import require_create, require_delete, require_read, require_update
from app.models import Tool
from app.schemas.tool import ToolCreate, ToolResponse, ToolUpdate

from common_logging import get_logger

logger = get_logger(__name__)

router = APIRouter(tags=['tools'])

@router.get('/', response_model=list[ToolResponse])
def get_tools(skip: int=0, limit: int=100, db: Session=Depends(get_db), current_user: User=Depends(require_read('tools'))):
    tools = db.query(Tool).filter(not Tool.is_deleted, Tool.tenant_id == current_user.tenant_id).offset(skip).limit(limit).all()
    return tools

@router.get('/{tool_id}', response_model=ToolResponse)
def get_tool(tool_id: int, db: Session=Depends(get_db), current_user: User=Depends(require_read('tools'))):
    tool = db.query(Tool).filter(Tool.id == tool_id, not Tool.is_deleted, Tool.tenant_id == current_user.tenant_id).first()
    if not tool:
        raise HTTPException(status_code=404, detail='Tool not found')
    return tool

@router.post('/', response_model=ToolResponse)
def create_tool(tool_in: ToolCreate, db: Session=Depends(get_db), current_user: User=Depends(require_create('tools'))):
    tool = Tool(**tool_in.model_dump(), tenant_id=current_user.tenant_id, created_by=current_user.id)
    db.add(tool)
    db.commit()
    db.refresh(tool)
    logger.bind(tool_id=tool.id).info("Tool created")
    return tool

@router.put('/{tool_id}', response_model=ToolResponse)
def update_tool(tool_id: int, tool_in: ToolUpdate, db: Session=Depends(get_db), current_user: User=Depends(require_update('tools'))):
    tool = db.query(Tool).filter(Tool.id == tool_id, not Tool.is_deleted, Tool.tenant_id == current_user.tenant_id).first()
    if not tool:
        raise HTTPException(status_code=404, detail='Tool not found')
    for field, value in tool_in.model_dump(exclude_unset=True).items():
        setattr(tool, field, value)
    db.commit()
    db.refresh(tool)
    return tool

@router.delete('/{tool_id}')
def delete_tool(tool_id: int, db: Session=Depends(get_db), current_user: User=Depends(require_delete('tools'))):
    tool = db.query(Tool).filter(Tool.id == tool_id, not Tool.is_deleted, Tool.tenant_id == current_user.tenant_id).first()
    if not tool:
        raise HTTPException(status_code=404, detail='Tool not found')
    tool.is_deleted = True
    db.commit()
    logger.bind(tool_id=tool_id).info("Tool deleted")
    return {'message': 'Tool deleted'}

@router.post('/{tool_id}/execute')
def execute_tool(tool_id: int, params: dict[str, Any], db: Session=Depends(get_db), current_user: User=Depends(require_read('tools'))):
    tool = db.query(Tool).filter(Tool.id == tool_id, not Tool.is_deleted, Tool.tenant_id == current_user.tenant_id).first()
    if not tool:
        raise HTTPException(status_code=404, detail='Tool not found')
    from app.services.tool_executor import ToolExecutor
    executor = ToolExecutor()
    try:
        result = executor.execute(tool.code, params)
        logger.bind(tool_id=tool_id).info("Tool executed")
        return {'result': result, 'status': 'success'}
    except Exception as e:
        logger.bind(tool_id=tool_id).error("Tool execution failed", error=str(e))
        raise HTTPException(status_code=400, detail=str(e)) from None
