import uuid
import pytest
from fastapi import status
from app.database import get_database
from app.repositories.conversation_repository import get_or_create_conversation, get_conversation_by_session_id
from app.repositories.message_repository import create_message, get_messages_by_conversation_id

def test_send_message_api_flow(client):
    # 1. Register tenant & initialize session
    domain = f"msg-{uuid.uuid4().hex[:6]}.com"
    reg_resp = client.post("/api/v1/tenant/register", json={
        "domain": domain,
        "name": "Message Store"
    })
    site_id = reg_resp.json()["siteId"]
    
    headers = {"Origin": f"http://{domain}"}
    init_resp = client.post("/api/v1/session/init", json={"siteId": site_id}, headers=headers)
    session_id = init_resp.json()["sessionId"]
    
    # 2. Send message while RINGING / waiting for agent
    msg_resp1 = client.post("/api/v1/message", json={
        "sessionId": session_id,
        "message": "Hello World"
    })
    assert msg_resp1.status_code == status.HTTP_200_OK
    assert msg_resp1.json()["sessionId"] == session_id
    assert msg_resp1.json()["reply"] == "Please wait while we connect you to an agent."

def test_send_message_all_states(client):
    domain = f"states-{uuid.uuid4().hex[:6]}.com"
    reg_resp = client.post("/api/v1/tenant/register", json={
        "domain": domain,
        "name": "States Store"
    })
    site_id = reg_resp.json()["siteId"]

    headers = {"Origin": f"http://{domain}"}
    init_resp = client.post("/api/v1/session/init", json={"siteId": site_id}, headers=headers)
    session_id = init_resp.json()["sessionId"]

    # 1. State: RINGING
    r1 = client.post("/api/v1/message", json={"sessionId": session_id, "message": "First inquiry"})
    assert r1.status_code == status.HTTP_200_OK
    assert r1.json()["reply"] == "Please wait while we connect you to an agent."

    # 2. Transition to IN_CHAT
    client.post("/api/v1/handoff/accept", json={"sessionId": session_id})

    # State: IN_CHAT
    r2 = client.post("/api/v1/message", json={"sessionId": session_id, "message": "Second inquiry"})
    assert r2.status_code == status.HTTP_200_OK
    assert r2.json()["reply"] == "Message delivered to agent."

    # 3. Transition to ENDED
    client.post("/api/v1/handoff/end", json={"sessionId": session_id})

    # State: ENDED -> rejected with HTTP 400
    r3 = client.post("/api/v1/message", json={"sessionId": session_id, "message": "Third inquiry"})
    assert r3.status_code == status.HTTP_400_BAD_REQUEST
    assert "ended session" in r3.json()["detail"]

@pytest.mark.anyio
async def test_conversation_and_message_repositories():
    # Verify MongoDB conversation & message persistence repository functions
    db = get_database()
    session_id = f"sess_{uuid.uuid4().hex[:12]}"
    site_id = f"site_{uuid.uuid4().hex[:12]}"
    
    # 1. Get or create conversation (One session = One conversation)
    conv1 = await get_or_create_conversation(db, session_id, site_id)
    assert conv1["sessionId"] == session_id
    assert conv1["siteId"] == site_id
    assert conv1["status"] == "open"
    conv_id = conv1["conversationId"]
    
    # Re-querying should return same conversation
    conv2 = await get_or_create_conversation(db, session_id, site_id)
    assert conv2["conversationId"] == conv_id

    # 2. Create User message
    user_msg = await create_message(db, conv_id, session_id, "user", "Hello World")
    assert user_msg["conversationId"] == conv_id
    assert user_msg["role"] == "user"
    assert user_msg["content"] == "Hello World"
    
    # 3. Fetch messages by conversation ID
    messages = await get_messages_by_conversation_id(db, conv_id)
    assert len(messages) == 1
    assert messages[0]["content"] == "Hello World"

def test_send_message_unknown_session_id(client):
    msg_resp = client.post("/api/v1/message", json={
        "sessionId": "sess_nonexistent_999",
        "message": "Hello"
    })
    assert msg_resp.status_code == status.HTTP_404_NOT_FOUND
    assert "Session not found" in msg_resp.json()["detail"]

def test_send_message_validation_error(client):
    msg_resp = client.post("/api/v1/message", json={
        "sessionId": "sess_valid_format",
        "message": ""
    })
    assert msg_resp.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
