"""Tests for contact router (T05)."""
import pytest
from unittest.mock import AsyncMock, patch, MagicMock
from sqlalchemy import select

from app.models.contact import Contact


@pytest.mark.asyncio
async def test_contact_valid_returns_200(client):
    """POST /api/contact with valid data returns 200 and saves to contacts table."""
    with patch(
        "app.services.email_service.EmailService.send_contact_email",
        new_callable=AsyncMock,
        return_value=True,
    ):
        resp = await client.post("/api/contact", json={
            "name": "Max Mustermann",
            "email": "max@example.com",
            "phone": "+49 123 456789",
            "message": "Ich brauche eine PA-Anlage fuer ein Festival.",
            "privacy_consent": True,
        })
    assert resp.status_code == 200
    data = resp.json()
    assert data["success"] is True


@pytest.mark.asyncio
async def test_contact_invalid_email_returns_422(client):
    """POST /api/contact with invalid email returns 422."""
    resp = await client.post("/api/contact", json={
        "name": "Max Mustermann",
        "email": "not-an-email",
        "phone": "+49 123 456789",
        "message": "Test message",
        "privacy_consent": True,
    })
    assert resp.status_code == 422


@pytest.mark.asyncio
async def test_contact_privacy_consent_false_returns_422(client):
    """POST /api/contact with privacy_consent=false returns 422."""
    resp = await client.post("/api/contact", json={
        "name": "Max Mustermann",
        "email": "max@example.com",
        "phone": "+49 123 456789",
        "message": "Test message",
        "privacy_consent": False,
    })
    assert resp.status_code == 422


@pytest.mark.asyncio
async def test_contact_triggers_email(client):
    """POST /api/contact triggers send_contact_email on EmailService."""
    with patch(
        "app.services.email_service.EmailService.send_contact_email",
        new_callable=AsyncMock,
        return_value=True,
    ) as mock_send:
        resp = await client.post("/api/contact", json={
            "name": "Erika Musterfrau",
            "email": "erika@example.com",
            "phone": "+49 987 654321",
            "message": "Ich benoetige Beleuchtung fuer eine Gala.",
            "privacy_consent": True,
        })
    assert resp.status_code == 200
    mock_send.assert_awaited_once()
    call_args = mock_send.call_args[0][0]
    assert call_args["name"] == "Erika Musterfrau"
    assert call_args["email"] == "erika@example.com"
    assert call_args["message"] == "Ich benoetige Beleuchtung fuer eine Gala."


@pytest.mark.asyncio
async def test_contact_saved_to_db(client, test_db):
    """POST /api/contact saves a record to the contacts table."""
    with patch(
        "app.services.email_service.EmailService.send_contact_email",
        new_callable=AsyncMock,
        return_value=True,
    ):
        resp = await client.post("/api/contact", json={
            "name": "DB Testuser",
            "email": "db@example.com",
            "phone": "+49 111 222333",
            "message": "Datenbank-Verifikation",
            "privacy_consent": True,
        })
    assert resp.status_code == 200

    result = await test_db.execute(select(Contact).where(Contact.email == "db@example.com"))
    contact = result.scalar_one_or_none()
    assert contact is not None
    assert contact.name == "DB Testuser"
    assert contact.message == "Datenbank-Verifikation"
    assert contact.privacy_consent is True
    assert contact.email_sent is True


@pytest.mark.asyncio
async def test_contact_email_failure_does_not_break_response(client):
    """POST /api/contact still returns 200 when email sending fails."""
    with patch(
        "app.services.email_service.EmailService.send_contact_email",
        new_callable=AsyncMock,
        return_value=False,
    ):
        resp = await client.post("/api/contact", json={
            "name": "Fail Test",
            "email": "fail@example.com",
            "phone": "+49 000 000000",
            "message": "Email soll fehlschlagen",
            "privacy_consent": True,
        })
    assert resp.status_code == 200
    assert resp.json()["success"] is True
