"""Background decorator that handles job enqueuing and execution."""
import json
from typing import Any, Callable

from fastapi import HTTPException, Request

from .client import enqueue_job
from .config import WEBHOOK_SECRET
from .webhook import verify_signature


def background() -> Callable[[Callable[..., Any]], Callable[..., Any]]:
    """
    Decorator that turns a FastAPI endpoint into a background job.

    - When a client calls the endpoint: enqueues job to Relayway API
    - When the worker calls back: verifies signature and executes function

    Reads RELAYWAY_WEBHOOK_SECRET from environment.

    Example:
        from relayway import background

        @app.post("/send-email")
        @background()
        async def send_email(data: dict) -> dict:
            send_actual_email(data["to"], data["subject"])
            return {"sent": True}
    """

    def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
        async def wrapper(request: Request) -> Any:
            body_bytes = await request.body()
            body_str = body_bytes.decode()

            signature = request.headers.get("X-Signature")
            timestamp_str = request.headers.get("X-Timestamp")

            if signature and timestamp_str:
                # Worker callback - verify and execute
                if not WEBHOOK_SECRET:
                    raise HTTPException(status_code=500, detail="RELAYWAY_WEBHOOK_SECRET not configured")

                is_valid = verify_signature(
                    secret=WEBHOOK_SECRET,
                    signature=signature,
                    timestamp=int(timestamp_str),
                    payload=body_str
                )

                if not is_valid:
                    raise HTTPException(status_code=401, detail="Invalid signature")

                data = json.loads(body_str)
                return await func(data)

            else:
                # Client request - enqueue job
                data = json.loads(body_str) if body_str else {}
                origin = str(request.url)
                result = enqueue_job(payload=data, origin=origin)
                return result

        wrapper.__name__ = func.__name__
        return wrapper

    return decorator
