"""Tests for the background decorator."""
import hashlib
import hmac
import json
import time
from unittest.mock import AsyncMock, Mock

import pytest

from relayway.decorator import background


def create_mock_request(body: dict, headers: dict = None, url: str = "http://localhost/endpoint"):
    """Create a mock FastAPI Request object."""
    request = AsyncMock()
    request.body.return_value = json.dumps(body).encode()
    request.headers = headers or {}
    request.url = url
    return request


@pytest.mark.asyncio
async def test_decorator_enqueues_job_when_no_signature(monkeypatch):
    """Client request without signature should enqueue job."""
    monkeypatch.setattr("relayway.decorator.WEBHOOK_SECRET", "whsec_test")

    enqueue_calls = []

    def mock_enqueue(payload, origin):
        enqueue_calls.append({"payload": payload, "origin": origin})
        return {"id": "task-123", "status": "pending"}

    monkeypatch.setattr("relayway.decorator.enqueue_job", mock_enqueue)

    @background()
    async def my_endpoint(data: dict):
        return {"processed": True}

    request = create_mock_request(
        body={"to": "test@example.com"},
        headers={},  # No signature headers
        url="http://customer.com/send-email"
    )

    result = await my_endpoint(request)

    assert result == {"id": "task-123", "status": "pending"}
    assert len(enqueue_calls) == 1
    assert enqueue_calls[0]["payload"] == {"to": "test@example.com"}
    assert enqueue_calls[0]["origin"] == "http://customer.com/send-email"


@pytest.mark.asyncio
async def test_decorator_executes_function_with_valid_signature(monkeypatch):
    """Worker callback with valid signature should execute function."""
    secret = "whsec_test"
    monkeypatch.setattr("relayway.decorator.WEBHOOK_SECRET", secret)

    payload = {"to": "test@example.com"}
    payload_str = json.dumps(payload)
    timestamp = int(time.time())

    # Generate valid signature
    message = f"{timestamp}.{payload_str}"
    signature = hmac.new(
        secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

    @background()
    async def my_endpoint(data: dict):
        return {"processed": True, "to": data["to"]}

    request = create_mock_request(
        body=payload,
        headers={"X-Signature": signature, "X-Timestamp": str(timestamp)}
    )

    result = await my_endpoint(request)

    assert result == {"processed": True, "to": "test@example.com"}


@pytest.mark.asyncio
async def test_decorator_rejects_invalid_signature(monkeypatch):
    """Worker callback with invalid signature should return 401."""
    monkeypatch.setattr("relayway.decorator.WEBHOOK_SECRET", "whsec_test")

    @background()
    async def my_endpoint(data: dict):
        return {"processed": True}

    request = create_mock_request(
        body={"to": "test@example.com"},
        headers={"X-Signature": "invalid_signature", "X-Timestamp": "1234567890"}
    )

    from fastapi import HTTPException

    with pytest.raises(HTTPException) as exc_info:
        await my_endpoint(request)

    assert exc_info.value.status_code == 401
    assert "Invalid signature" in exc_info.value.detail


@pytest.mark.asyncio
async def test_decorator_rejects_when_webhook_secret_not_configured(monkeypatch):
    """Should return 500 if WEBHOOK_SECRET is not set."""
    monkeypatch.setattr("relayway.decorator.WEBHOOK_SECRET", None)

    @background()
    async def my_endpoint(data: dict):
        return {"processed": True}

    request = create_mock_request(
        body={"to": "test@example.com"},
        headers={"X-Signature": "some_sig", "X-Timestamp": "1234567890"}
    )

    from fastapi import HTTPException

    with pytest.raises(HTTPException) as exc_info:
        await my_endpoint(request)

    assert exc_info.value.status_code == 500
    assert "RELAYWAY_WEBHOOK_SECRET not configured" in exc_info.value.detail
