import json
import logging
from datetime import date, timedelta

from typing import Any, AsyncIterable
from fastapi import APIRouter, HTTPException
from sse_starlette.sse import EventSourceResponse

from app.agents import HotelAgent
from app.agents.tool_map import tool_map
from app.schemas.chat import ChatRequest
from app.configs.settings import settings
from app.utils.store_conversation import create_conversation, save_conversation
from app.agents.tools.search_room_tool import get_available_dates


router = APIRouter()
logger = logging.getLogger(__name__)
    
@router.post(
    "/stream",
    summary="stream chat",
    status_code=200,
)
async def chat(args:ChatRequest):
    
    async def send_message() -> AsyncIterable[Any]:
        try:

            if not args.conversation_id:
                args.conversation_id = await create_conversation(args.question)
                    
            today = date.today().strftime("%d %B, %Y")
            max_future_booking_allowed = date.today() + timedelta(days=365)
            checkin, checkout = await get_available_dates()
            
            agent = HotelAgent(model="gpt-5.1", api_key=settings.OPENAI_API_KEY, conversation_id=args.conversation_id)

            async for token in agent.stream(input={
                'question': args.question,
                'date': today, 
                'checkin': checkin,
                'checkout': checkout,
                'context': json.dumps(args.roomList),
                'max_future_booking_allowed': max_future_booking_allowed
            }, history=args.history):
                if token == "\n":
                    token = "<br>"
                yield token


            async for token in tool_map(agent.result, args, checkin, checkout):
                yield token

            if args.conversation_id:
                yield "#conv_id:" + args.conversation_id
                await save_conversation(args.conversation_id, args.question, agent.result.answer, args.customer_id)
        
        except Exception as e:
            logger.error(f"Error: {str(e)}")
            raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
    return EventSourceResponse(send_message())