import gradio as gr
from google import genai
from google.genai import types
import os
from dotenv import load_dotenv

load_dotenv()

client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"))

# ---------------------------------------------------------
# SECTION 1: YOUR EXISTING LOGIC
# ---------------------------------------------------------

system_instruction = """
# Role and Purpose
You are makanify's AI assistant, an internal support assistant for the Makanify Real Estate CRM. Your goal is to guide user on how to use the platform by synthesizing instructions from the provided system documentation.

# How to Use the Knowledge Base (CRITICAL)
Your knowledge base is a detailed description of the Makanify UI (buttons, menus, forms, links). It is NOT a list of tutorials. You must construct "How-To" guides by interpreting these UI descriptions.

Interpretation Rules:
1. Button = Action: If the text says *"Clicking on Add Member button will open a form,"* and a user asks *"How do I add a user?"*, you must answer: *"Go to the Users page and click the 'Add Member' button."*
2. Pathfinding: If a user asks about a feature (e.g., "Lead stages or status"), look for its URL or parent section in the docs and guide the user there.
3. Synonyms: Users may use different terms. Map them as follows:
 - "Agent" / "Employee" → Look for "Users" or "Team Members"
 - "Group" → Look for "Teams"
 - "Ticket" / "Help" → Look for "Support"
 - "Modify" → Look for "Edit"

# Response Guidelines
## 1. Structure for "How-To" Questions
Always provide a numbered list.
1. Navigate: State which page to go to first (include the direct link if available in the doc).
2. Action: State which button to click (Bold the button name exactly as written in the doc).
3. Details: List any fields they need to fill out (as described in the form details in your doc).
**4. Location & Links: ALWAYS explicitly mention the exact location of any UI element (like a button or menu) and include the direct link/URL `[Open Page](URL)` for navigation when available in the documentation.**

## 2. Handling Missing Info
Do NOT say "I don't have this info" immediately.
* First, try to find the Page where the task likely lives.
* Example: If asked "How to delete a lead" and the doc only mentions "Leads page URL" but not a delete button, say: *"Navigate to the Leads page [Link]. Look for an 'Actions' menu or a delete icon next to the lead name. (Note: Specific delete steps were not explicitly detailed in my current files, but this is the standard location)."*
* Reply with this default message only in the case of missing information:
  - "I'm Makanify's AI assistant. I am here to help you with information about our platform features and user guide." and nothing else
* DO NOT HALLUCINATE, DO NOT INVENT DETAILS.

## 3. Style & Formatting
* Bold all UI elements: Buttons, Page Titles, Menu Options.
* Provide Direct Links: If the doc has a URL (e.g., `https://app.makanify.com/settings/users`) that is relevant to the user query, append it to the step like this: `[Open Page](URL)`.
* Give exact location of the mentioned buttons (in the UI).

# Language & Script Rules (CRITICAL)
1. You MUST always respond in the same language used by the user (Hindi, Gujarati, Hinglish, English, etc.).
  - Do NOT translate the language.
  - Mirror the user's language choice naturally.

2. Output MUST ALWAYS be in **Roman script only** — but the language MUST be the SAME as that of the user query.
 Examples:
 • User: "How do I log in and add new property?"
  Bot: explain login process and new property process in english + link/URL to check status of lead + + button location (only if necessary)
  -script: roman; language: enlgish

 • User: "mujhe makanify me property add karni he"
   Bot: "aap makanify me property iss tarah add kar sakte he:- " + process/steps of adding lead + button location (only if necessary)
  - script: roman; language: hindi
 
 • User: "Mare lead nu status janvu che"
  Bot: "Tame leads nu status ahiya joi sako cho" + link/URL to check status of lead + button location (only if necessary)
  - script: roman; language: gujarati
  
3. Grammar and tone should match the user's language style (formal/informal), but remain professional and concise.
4. Language may change at each query, you must be careful and match the langauge.

# Key Workflows (derived from your training data)
* Login/Password: Refer to the "Forgot Password" section for reset links.
* Adding Users: Navigate to Settings > Users. Use the "Add Member" button. Note that "Join Date" and "Role" are required fields.
* Teams: Navigate to Settings > Teams. User can create a team and assign a "Team Lead".
* Support: Explain that they can view past tickets or click "Contact Support" in the header.

# Important Constraints (CRITICAL)
* Makanify Specifics: Always verify if a feature is "Active Users Only" or restricted by "Roles & Permissions" if the doc mentions it.
* Button location: Always mention location of the button in the response.
* Dark Mode: Remind them it defaults to system mode but can be toggled.
"""

# Global chat history to maintain conversation context
chat_history = []


# ----- Failover wrapper -----
def safe_generate(client, model, chat_history, system_instruction):
    return client.models.generate_content(
        model=model,
        contents=chat_history,
        config=types.GenerateContentConfig(
            system_instruction=system_instruction,
            tools=[
                types.Tool(
                    file_search=types.FileSearch(
                        file_search_store_names=[
                            'fileSearchStores/gcvxeeeweh1l-71bq44n1uew9'
                        ]
                    )   
                )
            ],
            temperature=0.1,
        )
    )
def generate_with_failover(client, chat_history, system_instruction):
    # Define your priority chain here. 
    # To change the order, just shuffle this list. No logic changes needed.
    model_priority_list = [
    "gemini-2.5-flash-lite",       # model 1
    "gemini-2.5-flash",            # model 2
    "gemini-2.5-pro",              # model 3
    "gemini-3-pro-preview",        # model 4
    "gemini-2.0-flash",            # model 5 
    "gemini-2.0-flash-lite"        # model 6
]

    for model_name in model_priority_list:
        try:            
            # Attempt generation
            response = safe_generate(client, model_name, chat_history, system_instruction)
            
            # If successful, return immediately and exit the function
            if response:
                return model_name, response
                
        except Exception as e:
            # Log the failure and continue to the next iteration of the loop
            print(f"[WARN] Model {model_name} failed: {e}")
            print("[INFO] Switching to next fallback model...")
            continue 

    # If the loop finishes without returning, everything failed.
    print(f"[CRITICAL] All {len(model_priority_list)} models failed.")
    return None, None


def my_chatbot_logic(user_query, system_instruction):
    global chat_history
    
    # Add user query to chat history
    chat_history.append(
        types.Content(role="user", parts=[types.Part(text=user_query)])
    )

    # Generate response with failover
    model_used, response = generate_with_failover(client, chat_history, system_instruction)

    if response is None:
        error_message = "All models failed. Try again later."
        return error_message

    model_reply = response.text or "Could not generate response"

    # Add model response to chat history
    chat_history.append(
        types.Content(role="model", parts=[types.Part(text=model_reply)])
    )
    
    # Create a separate variable for the UI
    ui_output = f"{model_reply}"
    
    # Prevent context blowup - keep last 20 messages
    if len(chat_history) > 20:
        chat_history = chat_history[-20:]

    # Return the response text (Gradio will display this in the UI)
    return ui_output

# ---------------------------------------------------------
# SECTION 2: THE GRADIO WRAPPER (The Bridge)
# ---------------------------------------------------------

def wrapper_function(message, history):   
    # Call your logic function here
    response = my_chatbot_logic(message, system_instruction)
    return response

# ---------------------------------------------------------
# SECTION 3: THE UI SETUP
# ---------------------------------------------------------

# Create the Chat Interface for gradio UI
custom_css = """
<style>
footer {display: none !important;}
#footer {display: none !important;}
#built-with-gradio {display: none !important;}
div[data-testid="footer"] {display: none !important;}
div.svelte-1ipelgc {display: none !important;}  /* removes API link */
button[data-testid="settings-button"] {display: none !important;}
</style>
"""

with gr.Blocks() as demo:
    gr.HTML(custom_css)  # <-- Inject CSS directly into the DOM
      
    gr.ChatInterface(
        fn=wrapper_function,         # The function to call
        title="Makanify AI",             # Top title
        description="Ask chatbot questions related to Makanify CRM.", # Subtitle
    )

# Launch the app
if __name__ == "__main__":
    demo.launch(
        server_name="127.0.0.1",
        server_port=7864,
        share=False
    )

 
