from langchain_core.tools import tool
from typing import List, Dict
from vector_store import VectorStore
#from main2 import kbvector_store
import sqlalchemy
import mysql.connector
from mysql.connector import Error
from typing import Annotated
from langchain_core.messages import ToolMessage , AIMessage
from langgraph.graph import MessagesState
from langchain_core.tools import InjectedToolCallId
from langgraph.graph.message import add_messages
from typing_extensions import TypedDict
from langgraph.types import Command
from datetime import datetime, timedelta, timezone
from uuid import uuid4

request_id = str(uuid4())
vector_store = VectorStore()
class State(TypedDict):
    messages: Annotated[list, add_messages]
    name: str
    roomno : str
    
def get_current_time():
    """Return the current time in UTC as a formatted string."""
    return datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
    
@tool
def get_GuestDetails(guestname: str, room_no: str, tool_call_id: Annotated[str, InjectedToolCallId] ) -> str:
    """ 
    Captures guests name and Room number

    Args:
        name (str): Guest Name
        roomno (str): Guest Room Number 
    """
    print(f"**Invoking TOOL GetGuestDetails")
    print(f"guestname: {guestname} ,room no: {room_no}")
    
    state_update = {
        "name": guestname,
        "roomno": room_no,
        "messages": [ToolMessage("Thank you for providing Your name and Room No", tool_call_id=tool_call_id)],}
    print(f"GUESTNAME: {state_update['name']} ,room no: {state_update['roomno']}")
    return Command(update=state_update)


@tool
def tool_fnb(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer questions regarding ordering food and beverages. For example
        Can I order food to my room?
        Is the restaurant open now?

        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL FnB")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"GUESTNAMEFNB: {name} ,room no: {room_no}")
    # Generate a unique request ID for this specific request
    if name == "" or room_no == "Guest Room Number" or name== "required"or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest" or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    request_id = str(uuid4())
    
    sample_data = {
        "BUID": 1,
        "RequestID": request_id ,
        "ToDept": "3",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)

    query = vector_store.query_fnb(query=query)
    return query

@tool
def tool_reception(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer questions regarding the hotel and its Amenities Inquiries. For example: 
        where is the swimming pool located.
        What are the gym timings. Is there any train station nearby etcetera. 
        check out timings
        parking facilities. Can you arrange a taxi for me?
        Are there any good restaurants serving Arabian cuisine?
        Can you recommend restaurants near the hotel?
        Payment & Billing issue and other info enquires
        Can I split the bill between multiple payment methods
        I noticed a charge on my bill that I don't recognize. Can you help?

        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL Reception")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or  room_no == "Guest Room Number"or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "2",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)
    query = vector_store.query_reception(query=query)
    return query

@tool
def tool_catchall(query: str, state: Dict, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
    Captures queries that the bot cannot confidently answer and logs them for reception follow-up.
    
    Args:
        query (str): The unresolved user query
        state (Dict): Current conversation state
        tool_call_id (str): Unique tool call identifier

    Returns:
        Command to update the state and log the unresolved query
    """
    print(f"**Invoking TOOL Catchall for unresolved query")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or  room_no == "Guest Room Number"or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    # Prepare data for logging
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "2",  # Reception department
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "Unable to resolve query - Requires human intervention",
        "Status": "Unresolved",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "0",  # Indicates no staff has attended yet
        "GuestName": name
    }
    
    result = add_request(sample_data)
    print(result)


@tool
def tool_roomservice(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer regarding hotel's room service. For example
        Can I have a towel please
        Can I have a toothbrush please
        Can I get my room cleaned. Please help to clean my room
        I need a baby crib or cot
        Can I switch to a room with a better view . Room Preferences
        What are the pool hours?.
        What are the fitness center hours?
        Do you have vegetarian or special dietary options?
        what are breakfast hour or timings
        Can I get a couple of water bottles sent to my room
        
        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL Room Service")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or room_no == "Guest Room Number" or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "1",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)
    query = vector_store.query_roomservice(query=query)
    return query 

@tool
def tool_techhelp(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer questions AND helping them if they face any technical difficulty. for example
        My Wifi is not working
        My TV is now working. OR I am unable to get the TV channels
        Is there a business center where I can print documents?

        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL Tech Help")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or room_no == "Guest Room Number" or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "4",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)
    query = vector_store.query_techhelp(query=query)
    return query


@tool
def tool_concierge(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer questions AND helping them if they face any Concierge related difficulty. for example
        Does the hotel offer shuttle service to the airport?
        How do I get to the nearest subway/metro station. or Is there a good jogging path nearby?
        Can you recommend a good spa nearby?
        Do you offer babysitting services?
        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL Concierge")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or room_no == "Guest Room Number" or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "5",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)
    query = vector_store.query_concierge(query=query)
    return query


@tool
def tool_maintenance(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer questions AND helping them if they face any maintenance difficulty. for example
        The air conditioning in my room isn't working properly
        There's a light bulb out in my bathroom
        The shower drain is clogged.

        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL Maintenance")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or  room_no == "Guest Room Number" or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "7",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)
    query = vector_store.query_maintenance(query=query)
    return query


@tool
def tool_security(query: str, state: State, tool_call_id: Annotated[str, InjectedToolCallId]) -> List[Dict[str, str]]:
    """
        Looks up information in a knowledge base to help with answering customer questions AND helping them if they face any safety and security related difficulty. for example
        I lost my room key. What should I do?
        What should I do in case of an emergency?
        Does the hotel have a safe in the room?

        Args:
            query (str): Question to ask the knowledge base

        Return:
            List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
    """
    print(f"**Invoking TOOL Security ")
    # Retrieve guest details from the state
    name = state.get("name")
    room_no = state.get("roomno")
    print(f"guestname: {name} ,room no: {room_no}")
     # Generate a unique request ID for this specific request
    request_id = str(uuid4())
    # Generate a unique request ID for this specific request
    if name == "" or name== "required" or name== "None" or name == "guest_name" or name == "Guest" or name == "Your name" or name == "guest"or name == "Guest Name":
        return Command(update={
            "messages": [ToolMessage("May I have your name please?🤗", tool_call_id=tool_call_id)]
        })
    if room_no == "" or room_no == "room_number" or room_no == "unknown" or room_no == "null" or room_no== "Room Number" or room_no == "Guest Room Number":
        return Command(update={
            "messages": [ToolMessage("May I have your room number, please?🤗", tool_call_id=tool_call_id)]
        })
    sample_data = {
        "BUID": 1,
        "RequestID": request_id,
        "ToDept": "8",
        "FromRoomNo": room_no,
        "RequestDescp": query,
        "BotResponse": "answer to query",
        "Status": "New",
        "RequestCreatedAt": get_current_time(),
        "LastUpdatedAt": get_current_time(),
        "AttendedBy": "1",
        "GuestName": name
    }
    result = add_request(sample_data)
    print (result)
    query = vector_store.query_security(query=query)
    return query


def add_request(data: dict) -> str:
    """Add a request to the t_requestmaster table in MySQL."""
    try:
        connection = get_mysql_connection()
        if connection:
            cursor = connection.cursor()
            sql_query = """
                INSERT INTO t_Requests(BUID,RequestID, ToDept, FromRoomNo, RequestDescp,BotResponse, Status, RequestCreatedAt,LastUpdatedAt,AttendedBy, GuestName)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """
            cursor.execute(sql_query, (
                data['BUID'],
                data['RequestID'],
                data['ToDept'],
                data['FromRoomNo'],
                data['RequestDescp'],
                data['BotResponse'],
                data['Status'],
                data['RequestCreatedAt'],
                data['LastUpdatedAt'],
                data['AttendedBy'],
                data['GuestName']
            ))
            connection.commit()
            return "Request added successfully."
    except Error as e:
        return f"Error: {str(e)}"
    finally:
        if connection and connection.is_connected():
            cursor.close()
            connection.close()


def get_mysql_connection():
    try:
        connection = mysql.connector.connect(
            host='157.173.210.15',     
            user='testagent1', 
            password='testagent1', 
            database='RoyalOrchid'        
        )
        if connection.is_connected():
            print("Connected to MySQL database")
            return connection
        else:
            print("ERROR Connecting to MySQL database")
            return None

    except Error as e:
        print(f"Error: {e}")
        return None