import pytest
from unittest.mock import patch, AsyncMock


@pytest.mark.asyncio
async def test_submit_feedback(client, auth_headers):
    """Test successful feedback submission — saves to DB and sends emails."""
    with patch("app.api.endpoints.feedback.settings") as mock_settings, \
         patch("app.api.endpoints.feedback.EmailService") as mock_email:
        mock_settings.FEEDBACK_EMAIL = "support@test.com"
        mock_email.send_feedback_email = AsyncMock(return_value=True)
        mock_email.send_feedback_confirmation_email = AsyncMock(return_value=True)

        response = await client.post(
            "/api/v1/feedback",
            json={
                "email": "test@example.com",
                "feedback_type": "Bug Report",
                "message": "Something is broken in the tree editor when I try to save.",
            },
            headers=auth_headers,
        )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert "submitted" in data["message"].lower()

    # Verify both emails were called
    mock_email.send_feedback_email.assert_called_once()
    mock_email.send_feedback_confirmation_email.assert_called_once()


@pytest.mark.asyncio
async def test_submit_feedback_saves_to_db_even_if_email_fails(client, auth_headers, test_db):
    """Test that feedback is persisted even when email sending fails."""
    from sqlalchemy import select, func
    from app.models.feedback import Feedback

    with patch("app.api.endpoints.feedback.settings") as mock_settings, \
         patch("app.api.endpoints.feedback.EmailService") as mock_email:
        mock_settings.FEEDBACK_EMAIL = "support@test.com"
        mock_email.send_feedback_email = AsyncMock(return_value=False)
        mock_email.send_feedback_confirmation_email = AsyncMock(return_value=False)

        response = await client.post(
            "/api/v1/feedback",
            json={
                "email": "test@example.com",
                "feedback_type": "Feature Request",
                "message": "Please add dark mode to the export preview screen.",
            },
            headers=auth_headers,
        )

    # Should still succeed — DB write happened
    assert response.status_code == 200
    assert response.json()["success"] is True

    # Verify it was saved to the database
    result = await test_db.execute(select(func.count()).select_from(Feedback))
    count = result.scalar()
    assert count >= 1


@pytest.mark.asyncio
async def test_submit_feedback_not_configured(client, auth_headers):
    """Test 503 when FEEDBACK_EMAIL is not set."""
    with patch("app.api.endpoints.feedback.settings") as mock_settings:
        mock_settings.FEEDBACK_EMAIL = None

        response = await client.post(
            "/api/v1/feedback",
            json={
                "email": "test@example.com",
                "feedback_type": "General Feedback",
                "message": "This is a general feedback message for testing.",
            },
            headers=auth_headers,
        )

    assert response.status_code == 503


@pytest.mark.asyncio
async def test_submit_feedback_validation_message_too_short(client, auth_headers):
    """Test validation — message too short."""
    response = await client.post(
        "/api/v1/feedback",
        json={
            "email": "test@example.com",
            "feedback_type": "Bug Report",
            "message": "short",
        },
        headers=auth_headers,
    )

    assert response.status_code == 422


@pytest.mark.asyncio
async def test_submit_feedback_invalid_type(client, auth_headers):
    """Test validation — invalid feedback type."""
    response = await client.post(
        "/api/v1/feedback",
        json={
            "email": "test@example.com",
            "feedback_type": "Invalid Type",
            "message": "This should fail because the type is invalid.",
        },
        headers=auth_headers,
    )

    assert response.status_code == 422


@pytest.mark.asyncio
async def test_submit_feedback_requires_auth(client):
    """Test that unauthenticated requests are rejected."""
    response = await client.post(
        "/api/v1/feedback",
        json={
            "email": "anon@example.com",
            "feedback_type": "General Feedback",
            "message": "This should fail because I'm not logged in.",
        },
    )
    assert response.status_code == 401
