from unittest.mock import MagicMock

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient

from control_backend.api.v1.endpoints import command
from control_backend.schemas.ri_message import SpeechCommand


@pytest.fixture
def app():
    """
    Creates a FastAPI test app and attaches the router under test.
    Also sets up a mock internal_comm_socket.
    """
    app = FastAPI()
    app.include_router(command.router)
    app.state.internal_comm_socket = MagicMock()  # mock ZMQ socket
    return app


@pytest.fixture
def client(app):
    """Create a test client for the app."""
    return TestClient(app)


def test_receive_command_endpoint(client, app):
    """
    Test that a POST to /command sends the right multipart message
    and returns a 202 with the expected JSON body.
    """
    mock_socket = app.state.internal_comm_socket

    # Prepare test payload that matches SpeechCommand
    payload = {"endpoint": "actuate/speech", "data": "yooo"}

    # Send POST request
    response = client.post("/command", json=payload)

    # Check response
    assert response.status_code == 202
    assert response.json() == {"status": "Command received"}

    # Verify that the socket was called with the correct data
    assert mock_socket.send_multipart.called, "Socket should be used to send data"

    args, kwargs = mock_socket.send_multipart.call_args
    sent_data = args[0]

    assert sent_data[0] == b"command"
    # Check JSON encoding roughly matches
    assert isinstance(SpeechCommand.model_validate_json(sent_data[1].decode()), SpeechCommand)


def test_receive_command_invalid_payload(client):
    """
    Test invalid data handling (schema validation).
    """
    # Missing required field(s)
    bad_payload = {"invalid": "data"}
    response = client.post("/command", json=bad_payload)
    assert response.status_code == 422  # validation error
