"""
Appointment State Management
=============================
Pure functions and async helpers for managing dp_conversations.appointment_status.

Appointment status values:
- 'NONE': No appointment discussion yet
- 'INVITED': Customer has shown vague interest (e.g., "Saturday morning")
- 'BOOKED': Customer has confirmed a specific time (e.g., "11am Saturday")

Transitions:
- NONE → INVITED: When tier == 'T3_APPOINTMENT' AND appointment_intent == 'vague'
- NONE/INVITED → BOOKED: When appointment_intent == 'specific'
- BOOKED: Terminal state for this conversation (stays BOOKED)
"""

from uuid import UUID
from app.db import get_conn


def compute_new_appointment_status(
    current_status: str | None,
    tier: str | None = None,
    appointment_intent: str = "none",
) -> str:
    """
    Pure function to compute the new appointment status.
    
    Args:
        current_status: 'NONE' | 'INVITED' | 'BOOKED' (None treated as 'NONE')
        tier: URE tier classification
        appointment_intent: 'none' | 'vague' | 'specific'
    
    Returns:
        New appointment status: 'NONE' | 'INVITED' | 'BOOKED'
    """
    status = current_status or "NONE"
    
    if status == "BOOKED":
        return "BOOKED"
    
    if appointment_intent == "specific":
        return "BOOKED"
    
    if status == "NONE" and appointment_intent == "vague" and tier == "T3_APPOINTMENT":
        return "INVITED"
    
    return status


async def update_appointment_status_if_changed(
    conversation_id: str,
    tier: str | None = None,
    appointment_intent: str = "none",
) -> dict:
    """
    Load conversation, compute new appointment status, and update if changed.
    
    Args:
        conversation_id: UUID string of the conversation
        tier: URE tier classification
        appointment_intent: 'none' | 'vague' | 'specific'
    
    Returns:
        Dict with old_status, new_status, and updated flag
    """
    conv_uuid = UUID(conversation_id)
    
    conn = await get_conn()
    try:
        row = await conn.fetchrow(
            """
            SELECT appointment_status
            FROM dp_conversations
            WHERE conversation_id = $1
            """,
            conv_uuid,
        )
        
        if not row:
            return {"error": "Conversation not found", "updated": False}
        
        current_status = row["appointment_status"] or "NONE"
        
        new_status = compute_new_appointment_status(
            current_status=current_status,
            tier=tier,
            appointment_intent=appointment_intent,
        )
        
        if new_status != current_status:
            await conn.execute(
                """
                UPDATE dp_conversations
                SET appointment_status = $2,
                    updated_at = NOW()
                WHERE conversation_id = $1
                """,
                conv_uuid,
                new_status,
            )
            return {
                "old_status": current_status,
                "new_status": new_status,
                "updated": True,
            }
        
        return {
            "old_status": current_status,
            "new_status": new_status,
            "updated": False,
        }
    
    finally:
        await conn.close()


def detect_appointment_intent(
    body_lower: str,
    is_specific_time_func=None,
    is_vague_time_window_func=None,
) -> str:
    """
    Detect the appointment intent from the customer message.
    
    This is a helper that can use the existing URE detection functions.
    
    Args:
        body_lower: Lowercased customer message
        is_specific_time_func: Optional function to detect specific times
        is_vague_time_window_func: Optional function to detect vague time windows
    
    Returns:
        'specific' | 'vague' | 'none'
    """
    if is_specific_time_func and is_specific_time_func(body_lower):
        return "specific"
    
    if is_vague_time_window_func and is_vague_time_window_func(body_lower):
        return "vague"
    
    return "none"
