from fastapi import APIRouter, status, HTTPException
from app.models.message import MessageRequest, MessageResponse
from app.repositories.session_repository import get_session_by_id
from app.repositories.conversation_repository import get_or_create_conversation
from app.repositories.message_repository import create_message
from app.database import get_database
from app.services.presence import active_sessions, broadcast_to_agents

router = APIRouter(prefix="/api/v1", tags=["message"])

@router.post("/message", response_model=MessageResponse, status_code=status.HTTP_200_OK)
async def send_message(payload: MessageRequest):
    db = get_database()
    
    # Step 1: Validate that the session exists in MongoDB
    session = await get_session_by_id(db, payload.sessionId)
    if not session:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Session not found for sessionId '{payload.sessionId}'"
        )
    
    site_id = session.get("siteId", "")
    
    # Step 2: Check session status (memory or DB)
    in_memory_session = active_sessions.get(payload.sessionId, {})
    in_memory_status = in_memory_session.get("status")
    db_status = session.get("status")
    current_status = in_memory_status or db_status

    if current_status == "ENDED":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Cannot send message to an ended session '{payload.sessionId}'"
        )

    # Step 3: Get or create conversation (One Session = One Conversation)
    conversation = await get_or_create_conversation(db, payload.sessionId, site_id)
    conversation_id = conversation["conversationId"]
    
    # Step 4: Persist USER message in MongoDB
    await create_message(
        db,
        conversation_id=conversation_id,
        session_id=payload.sessionId,
        role="user",
        content=payload.message
    )

    assigned_agent = in_memory_session.get("assignedAgentId") or session.get("assignedAgentId")

    # Step 5: Broadcast visitor message to Agent Dashboards including assignedAgentId
    await broadcast_to_agents({
        "type": "user_message",
        "sessionId": payload.sessionId,
        "siteId": site_id,
        "assignedAgentId": assigned_agent,
        "message": payload.message
    })

    # Step 6: Return state-specific response
    if current_status == "IN_CHAT":
        return MessageResponse(sessionId=payload.sessionId, reply="Message delivered to agent.")

    # RINGING or default waiting state
    return MessageResponse(
        sessionId=payload.sessionId,
        reply="Please wait while we connect you to an agent."
    )
