import os
import gradio as gr
import nltk
import numpy as np
import tflearn
import random
import json
import pickle
from nltk.tokenize import word_tokenize
from nltk.stem.lancaster import LancasterStemmer
from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
import googlemaps
import folium
import pandas as pd
import torch

# Disable GPU usage for TensorFlow
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'

# Ensure necessary NLTK resources are downloaded
nltk.download('punkt')

# Initialize the stemmer
stemmer = LancasterStemmer()

# Load intents.json for Well-Being Chatbot
with open("intents.json") as file:
    data = json.load(file)

# Load preprocessed data for Well-Being Chatbot
with open("data.pickle", "rb") as f:
    words, labels, training, output = pickle.load(f)

# Build the model structure for Well-Being Chatbot
net = tflearn.input_data(shape=[None, len(training[0])])
net = tflearn.fully_connected(net, 8)
net = tflearn.fully_connected(net, 8)
net = tflearn.fully_connected(net, len(output[0]), activation="softmax")
net = tflearn.regression(net)

# Load the trained model
model = tflearn.DNN(net)
model.load("MentalHealthChatBotmodel.tflearn")

# Function to process user input into a bag-of-words format for Chatbot
def bag_of_words(s, words):
    bag = [0 for _ in range(len(words))]
    s_words = word_tokenize(s)
    s_words = [stemmer.stem(word.lower()) for word in s_words if word.lower() in words]
    for se in s_words:
        for i, w in enumerate(words):
            if w == se:
                bag[i] = 1
    return np.array(bag)

# Chat function for Well-Being Chatbot
def chatbot(message, history):
    history = history or []
    message = message.lower()
    try:
        # Predict the tag
        results = model.predict([bag_of_words(message, words)])
        results_index = np.argmax(results)
        tag = labels[results_index]

        # Match tag with intent and choose a random response
        for tg in data["intents"]:
            if tg['tag'] == tag:
                responses = tg['responses']
                response = random.choice(responses)
                break
        else:
            response = "I'm sorry, I didn't understand that. Could you please rephrase?"
    except Exception as e:
        response = f"An error occurred: {str(e)}"
    
    # Convert the new message and response to the 'messages' format
    history.append({"role": "user", "content": message})
    history.append({"role": "assistant", "content": response})
    
    return history, history

# Sentiment Analysis using Hugging Face model
tokenizer_sentiment = AutoTokenizer.from_pretrained("cardiffnlp/twitter-roberta-base-sentiment")
model_sentiment = AutoModelForSequenceClassification.from_pretrained("cardiffnlp/twitter-roberta-base-sentiment")

def analyze_sentiment(user_input):
    inputs = tokenizer_sentiment(user_input, return_tensors="pt")
    with torch.no_grad():
        outputs = model_sentiment(**inputs)
    predicted_class = torch.argmax(outputs.logits, dim=1).item()
    sentiment = ["Negative", "Neutral", "Positive"][predicted_class]  # Assuming 3 classes
    return f"Predicted Sentiment: {sentiment}"

# Emotion Detection using Hugging Face model
tokenizer_emotion = AutoTokenizer.from_pretrained("j-hartmann/emotion-english-distilroberta-base")
model_emotion = AutoModelForSequenceClassification.from_pretrained("j-hartmann/emotion-english-distilroberta-base")

def detect_emotion(user_input):
    pipe = pipeline("text-classification", model=model_emotion, tokenizer=tokenizer_emotion)
    result = pipe(user_input)
    emotion = result[0]['label']
    return f"Emotion Detected: {emotion}"

# Initialize Google Maps API client securely
gmaps = googlemaps.Client(key=os.getenv('GOOGLE_API_KEY'))

# Function to search for health professionals
def search_health_professionals(query, location, radius=10000):
    places_result = gmaps.places_nearby(location, radius=radius, type='doctor', keyword=query)
    return places_result.get('results', [])

# Function to get directions and display on Gradio UI
def get_health_professionals_and_map(current_location, health_professional_query):
    location = gmaps.geocode(current_location)
    if location:
        lat = location[0]["geometry"]["location"]["lat"]
        lng = location[0]["geometry"]["location"]["lng"]
        location = (lat, lng)
        
        professionals = search_health_professionals(health_professional_query, location)
        
        # Generate map
        map_center = location
        m = folium.Map(location=map_center, zoom_start=13)
        
        # Add markers to the map
        for place in professionals:
            folium.Marker(
                location=[place['geometry']['location']['lat'], place['geometry']['location']['lng']],
                popup=place['name']
            ).add_to(m)
        
        # Convert map to HTML for Gradio display
        map_html = m._repr_html_()
        
        # Route information
        route_info = "\n".join([f"{place['name']} - {place['vicinity']}" for place in professionals])
        
        return route_info, map_html
    else:
        return "Unable to find location.", ""

# Function to generate suggestions based on the detected emotion
def generate_suggestions(emotion):
    suggestions = {
        'joy': [
            {"Title": "Relaxation Techniques", "Subject": "Relaxation", "Link": '<a href="https://www.helpguide.org/mental-health/meditation/mindful-breathing-meditation" target="_blank">Mindful Breathing Meditation</a>'},
            {"Title": "Dealing with Stress", "Subject": "Stress Management", "Link": '<a href="https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety" target="_blank">Tips for Dealing with Anxiety</a>'},
            {"Title": "Emotional Wellness Toolkit", "Subject": "Wellness", "Link": '<a href="https://www.nih.gov/health-information/emotional-wellness-toolkit" target="_blank">Emotional Wellness Toolkit</a>'},
            {"Title": "Relaxation Video", "Subject": "Video", "Link": '<a href="https://youtu.be/m1vaUGtyo-A" target="_blank">Watch Video</a>'}
        ],
        'anger': [
            {"Title": "Emotional Wellness Toolkit", "Subject": "Wellness", "Link": '<a href="https://www.nih.gov/health-information/emotional-wellness-toolkit" target="_blank">Emotional Wellness Toolkit</a>'},
            {"Title": "Stress Management Tips", "Subject": "Stress Management", "Link": '<a href="https://www.health.harvard.edu/health-a-to-z" target="_blank">Harvard Health: Stress Management</a>'},
            {"Title": "Dealing with Anger", "Subject": "Anger Management", "Link": '<a href="https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety" target="_blank">Tips for Dealing with Anger</a>'},
            {"Title": "Relaxation Video", "Subject": "Video", "Link": '<a href="https://youtu.be/MIc299Flibs" target="_blank">Watch Video</a>'}
        ],
        'fear': [
            {"Title": "Mindfulness Practices", "Subject": "Mindfulness", "Link": '<a href="https://www.helpguide.org/mental-health/meditation/mindful-breathing-meditation" target="_blank">Mindful Breathing Meditation</a>'},
            {"Title": "Coping with Anxiety", "Subject": "Anxiety Management", "Link": '<a href="https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety" target="_blank">Tips for Dealing with Anxiety</a>'},
            {"Title": "Emotional Wellness Toolkit", "Subject": "Wellness", "Link": '<a href="https://www.nih.gov/health-information/emotional-wellness-toolkit" target="_blank">Emotional Wellness Toolkit</a>'},
            {"Title": "Relaxation Video", "Subject": "Video", "Link": '<a href="https://youtu.be/yGKKz185M5o" target="_blank">Watch Video</a>'}
        ],
        'sadness': [
            {"Title": "Emotional Wellness Toolkit", "Subject": "Wellness", "Link": '<a href="https://www.nih.gov/health-information/emotional-wellness-toolkit" target="_blank">Emotional Wellness Toolkit</a>'},
            {"Title": "Dealing with Anxiety", "Subject": "Anxiety Management", "Link": '<a href="https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety" target="_blank">Tips for Dealing with Anxiety</a>'},
            {"Title": "Relaxation Video", "Subject": "Video", "Link": '<a href="https://youtu.be/-e-4Kx5px_I" target="_blank">Watch Video</a>'}
        ],
        'surprise': [
            {"Title": "Managing Stress", "Subject": "Stress Management", "Link": '<a href="https://www.health.harvard.edu/health-a-to-z" target="_blank">Harvard Health: Stress Management</a>'},
            {"Title": "Coping Strategies", "Subject": "Coping", "Link": '<a href="https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety" target="_blank">Coping with Anxiety</a>'},
            {"Title": "Relaxation Video", "Subject": "Video", "Link": '<a href="https://youtu.be/m1vaUGtyo-A" target="_blank">Watch Video</a>'}
        ]
    }

    return suggestions.get(emotion, [])

# Gradio interface
def gradio_app(message, location, health_query, submit_button, history, state):
    if submit_button:
        # Chatbot interaction
        history, _ = chatbot(message, history)
        
        # Sentiment analysis
        sentiment_response = analyze_sentiment(message)
        
        # Emotion detection
        emotion_response = detect_emotion(message)
        
        # Health professional search and map display
        route_info, map_html = get_health_professionals_and_map(location, health_query)
        
        # Generate suggestions based on the detected emotion
        suggestions = generate_suggestions(emotion_response.split(': ')[1])
        
        # Create a DataFrame for displaying suggestions
        suggestions_df = pd.DataFrame(suggestions)
        
        return history, sentiment_response, emotion_response, route_info, map_html, gr.DataFrame(suggestions_df, headers=["Title", "Subject", "Link"]), state
    else:
        return history, "", "", "", "", gr.DataFrame([], headers=["Title", "Subject", "Link"]), state

# Gradio UI components
message_input = gr.Textbox(lines=1, label="Message")
location_input = gr.Textbox(value="Honolulu, HI", label="Current Location")
health_query_input = gr.Textbox(value="doctor", label="Health Professional Query (e.g., doctor, psychiatrist, psychologist)")
submit_button = gr.Button("Submit")

# Updated chat history component with 'messages' type
chat_history = gr.Chatbot(label="Well-Being Chat History", type='messages')

# Outputs
sentiment_output = gr.Textbox(label="Sentiment Analysis Result")
emotion_output = gr.Textbox(label="Emotion Detection Result")
route_info_output = gr.Textbox(label="Health Professionals Information")
map_output = gr.HTML(label="Map with Health Professionals")
suggestions_output = gr.DataFrame(label="Well-Being Suggestions", headers=["Title", "Subject", "Link"])

# Create Gradio interface
iface = gr.Interface(
    fn=gradio_app, 
    inputs=[message_input, location_input, health_query_input, submit_button, gr.State()],
    outputs=[chat_history, sentiment_output, emotion_output, route_info_output, map_output, suggestions_output, gr.State()],
    allow_flagging="never",
    live=False,
    title="Well-Being App: Support, Sentiment, Emotion Detection & Health Professional Search"
)

# Launch the Gradio interface
iface.launch()
enhance my code and improve it by adding and adjusting features. FIrst think then reason and then share the full updated code.