import httpx
from loguru import logger
from fastapi import HTTPException
from enum import Enum
from typing import Any
from service_forge.workflow.node import Node
from service_forge.workflow.port import Port

class CallServiceNodeMethod(Enum):
    GET = "GET"
    POST = "POST"
    PUT = "PUT"
    DELETE = "DELETE"

class CallServiceNode(Node):
    DEFAULT_INPUT_PORTS = [
        Port("service_name", str),
        Port("version", str),
        Port("path", str),
        Port("path_params", dict),
        Port("method", CallServiceNodeMethod),
        Port("data", dict),
        Port("response_type", type),
        Port("user_id", str),
        Port("token", str),
    ]

    DEFAULT_OUTPUT_PORTS = [
        Port("response", Any),
        Port("status_code", int),
    ]

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

    async def _run(
        self,
        service_name: str,
        version: str,
        path: str,
        path_params: dict,
        method: CallServiceNodeMethod,
        data: dict,
        response_type: type,
        user_id: str,
        token: str,
    ) -> Any:
        url = self.get_url(
            service_name=service_name,
            version=version,
            path=path,
            path_params=path_params,
        )
        logger.debug(f"CallServiceNode._run: url: {url} method: {method} data: {data} user_id: {user_id} token: {token}")
        headers = {
            "X-User-ID": user_id,
            "X-Auth-Token": token,
            "Authorization": f"Bearer {token}",
        }
        async with httpx.AsyncClient() as client:
            response = await client.request(
                method.value,
                url,
                json=data,
                headers=headers,
            )

            self.activate_output_edges('status_code', response.status_code)
            if response.status_code == 200:
                self.activate_output_edges('response', response.json())
            else:
                raise HTTPException(status_code=response.status_code, detail=response.json())
