from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock, AsyncMock
from sqlalchemy.orm import Session

from app.app import create_app
from app.api.dependencies import get_db

# --- Dependency Override for Testing ---
mock_db = MagicMock(spec=Session)
def override_get_db():
    try:
        yield mock_db
    finally:
        pass

# --- API Endpoint Tests ---

def test_read_root():
    """Test the root endpoint to ensure it's running."""
    app = create_app()
    client = TestClient(app)
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"status": "AI Model Hub is running!"}

@patch('app.app.RAGService')
def test_chat_handler_success(mock_rag_service_class):
    """
    Test the /chat endpoint with a successful, mocked RAG service response.
    """
    # Arrange
    mock_rag_service_instance = mock_rag_service_class.return_value
    mock_rag_service_instance.chat_with_rag = AsyncMock(return_value="This is a mock response.")
    app = create_app()
    app.dependency_overrides[get_db] = override_get_db
    client = TestClient(app)
    # This payload is now valid according to the ChatRequest Pydantic model
    payload = {"prompt": "Hello there", "model": "deepseek"}

    # Act
    response = client.post("/chat", json=payload)

    # Assert
    assert response.status_code == 200
    assert response.json()["answer"] == "This is a mock response."
    assert response.json()["model_used"] == "deepseek"
    mock_rag_service_instance.chat_with_rag.assert_called_once_with(
        db=mock_db, prompt="Hello there", model="deepseek"
    )

@patch('app.app.RAGService')
def test_chat_handler_api_failure(mock_rag_service_class):
    """
    Test the /chat endpoint when the RAG service encounters an error.
    """
    # Arrange
    mock_rag_service_instance = mock_rag_service_class.return_value
    mock_rag_service_instance.chat_with_rag = AsyncMock(side_effect=Exception("API connection error"))
    app = create_app()
    app.dependency_overrides[get_db] = override_get_db
    client = TestClient(app)
    # This payload is now valid according to the ChatRequest Pydantic model
    payload = {"prompt": "This request will fail", "model": "deepseek"}

    # Act
    response = client.post("/chat", json=payload)

    # Assert
    assert response.status_code == 500
    assert "An unexpected error occurred with the deepseek API" in response.json()["detail"]
    mock_rag_service_instance.chat_with_rag.assert_called_once_with(
        db=mock_db, prompt="This request will fail", model="deepseek"
    )