from typing import Any
from loguru import logger
from pydantic import BaseModel
from service_forge.workflow.node import Node
from service_forge.workflow.port import Port

class DatabaseCastNode(Node):
    DEFAULT_INPUT_PORTS = [
        Port("object", Any),
        Port("cast_type", type),
    ]

    DEFAULT_OUTPUT_PORTS = [
        Port("object", Any),
    ]

    def __init__(self, name: str):
        super().__init__(name)

    async def _run(self, object: Any, cast_type: type) -> None:
        if not isinstance(cast_type, type):
            raise ValueError(f"cast_type must be a class type, got {type(cast_type)}")
        
        if not (hasattr(cast_type, '__table__') or hasattr(cast_type, '__mapper__')):
            raise ValueError(f"cast_type must be a SQLAlchemy model class (inherited from declarative_base()), got {cast_type}")
        
        if isinstance(object, cast_type):
            logger.debug(f"Data is already an instance of {cast_type.__name__}")
            self.activate_output_edges(self.get_output_port_by_name('object'), object)
            return
        
        if isinstance(object, BaseModel):
            object_dict = object.model_dump()
        elif isinstance(object, dict):
            object_dict = object
        else:
            raise ValueError(f"object must be a dict or BaseModel instance, got {type(object)}")
        
        try:
            instance = cast_type(**object_dict)
            logger.debug(f"✓ Cast data to {cast_type.__name__} instance")
            self.activate_output_edges(self.get_output_port_by_name('object'), instance)
        except Exception as e:
            logger.error(f"✗ Failed to cast data to {cast_type.__name__}: {e}")
            raise ValueError(f"Failed to cast data to {cast_type.__name__}: {e}")