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 torch

# Suppress TensorFlow warnings
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"

# Download necessary NLTK resources
nltk.download("punkt")
stemmer = LancasterStemmer()

# Load intents and chatbot training data
with open("intents.json") as file:
    intents_data = json.load(file)

with open("data.pickle", "rb") as f:
    words, labels, training, output = pickle.load(f)

# Build the chatbot model
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)
chatbot_model = tflearn.DNN(net)
chatbot_model.load("MentalHealthChatBotmodel.tflearn")

# Hugging Face sentiment and emotion models
tokenizer_sentiment = AutoTokenizer.from_pretrained("cardiffnlp/twitter-roberta-base-sentiment")
model_sentiment = AutoModelForSequenceClassification.from_pretrained("cardiffnlp/twitter-roberta-base-sentiment")
tokenizer_emotion = AutoTokenizer.from_pretrained("j-hartmann/emotion-english-distilroberta-base")
model_emotion = AutoModelForSequenceClassification.from_pretrained("j-hartmann/emotion-english-distilroberta-base")

# Google Maps API Client
gmaps = googlemaps.Client(key=os.getenv("GOOGLE_API_KEY"))

# Disease dictionary to map disease names to numerical values
disease_dict = { 
    'Fungal infection': 0, 'Allergy': 1, 'GERD': 2, 'Chronic cholestasis': 3, 'Drug Reaction': 4,
    'Peptic ulcer disease': 5, 'AIDS': 6, 'Diabetes ': 7, 'Gastroenteritis': 8, 'Bronchial Asthma': 9,
    'Hypertension ': 10, 'Migraine': 11, 'Cervical spondylosis': 12, 'Paralysis (brain hemorrhage)': 13,
    'Jaundice': 14, 'Malaria': 15, 'Chicken pox': 16, 'Dengue': 17, 'Typhoid': 18, 'hepatitis A': 19,
    'Hepatitis B': 20, 'Hepatitis C': 21, 'Hepatitis D': 22, 'Hepatitis E': 23, 'Alcoholic hepatitis': 24,
    'Tuberculosis': 25, 'Common Cold': 26, 'Pneumonia': 27, 'Dimorphic hemorrhoids(piles)': 28,
    'Heart attack': 29, 'Varicose veins': 30, 'Hypothyroidism': 31, 'Hyperthyroidism': 32,
    'Hypoglycemia': 33, 'Osteoarthritis': 34, 'Arthritis': 35,
    '(vertigo) Paroxysmal Positional Vertigo': 36, 'Acne': 37, 'Urinary tract infection': 38,
    'Psoriasis': 39, 'Impetigo': 40
}

# Helper Functions
def bag_of_words(s, words):
    """Convert user input to bag-of-words vector."""
    bag = [0] * len(words)
    s_words = word_tokenize(s)
    s_words = [stemmer.stem(word.lower()) for word in s_words if word.isalnum()]
    for se in s_words:
        for i, w in enumerate(words):
            if w == se:
                bag[i] = 1
    return np.array(bag)

def generate_chatbot_response(message, history):
    """Generate chatbot response and maintain conversation history."""
    history = history or []
    try:
        result = chatbot_model.predict([bag_of_words(message, words)])
        tag = labels[np.argmax(result)]
        response = "I'm sorry, I didn't understand that. 🤔"
        for intent in intents_data["intents"]:
            if intent["tag"] == tag:
                response = random.choice(intent["responses"])
                break
    except Exception as e:
        response = f"Error: {e}"
    history.append((message, response))
    return history, response

def analyze_sentiment(user_input):
    """Analyze sentiment and map to emojis."""
    inputs = tokenizer_sentiment(user_input, return_tensors="pt")
    with torch.no_grad():
        outputs = model_sentiment(**inputs)
    sentiment_class = torch.argmax(outputs.logits, dim=1).item()
    sentiment_map = ["Negative 😔", "Neutral 😐", "Positive 😊"]
    return f"Sentiment: {sentiment_map[sentiment_class]}"

def detect_emotion(user_input):
    """Detect emotions based on input."""
    pipe = pipeline("text-classification", model=model_emotion, tokenizer=tokenizer_emotion)
    result = pipe(user_input)
    emotion = result[0]["label"].lower().strip()
    emotion_map = {
        "joy": "Joy 😊",
        "anger": "Anger 😠",
        "sadness": "Sadness 😢",
        "fear": "Fear 😨",
        "surprise": "Surprise 😲",
        "neutral": "Neutral 😐",
    }
    return emotion_map.get(emotion, "Unknown 🤔"), emotion

def disease_prediction(user_input):
    """Predict disease based on input symptoms."""
    # Here, we simulate disease prediction logic
    symptoms = user_input.lower().split()
    disease_probabilities = [random.random() for _ in disease_dict]  # Placeholder for prediction model
    
    # Select the highest probability (for demonstration)
    disease_index = np.argmax(disease_probabilities)
    disease_name = list(disease_dict.keys())[disease_index]
    return disease_name

def generate_suggestions(emotion):
    """Return relevant suggestions based on detected emotions."""
    emotion_key = emotion.lower()
    suggestions = {
        "joy": [
            ["Relaxation Techniques", "https://www.helpguide.org/mental-health/meditation/mindful-breathing-meditation"],
            ["Dealing with Stress", "https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety"],
            ["Emotional Wellness Toolkit", "https://www.nih.gov/health-information/emotional-wellness-toolkit"],
            ["Relaxation Video", "https://youtu.be/m1vaUGtyo-A"],
        ],
        "anger": [
            ["Emotional Wellness Toolkit", "https://www.nih.gov/health-information/emotional-wellness-toolkit"],
            ["Stress Management Tips", "https://www.health.harvard.edu/health-a-to-z"],
            ["Dealing with Anger", "https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety"],
            ["Relaxation Video", "https://youtu.be/MIc299Flibs"],
        ],
        "fear": [
            ["Mindfulness Practices", "https://www.helpguide.org/mental-health/meditation/mindful-breathing-meditation"],
            ["Coping with Anxiety", "https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety"],
            ["Emotional Wellness Toolkit", "https://www.nih.gov/health-information/emotional-wellness-toolkit"],
            ["Relaxation Video", "https://youtu.be/yGKKz185M5o"],
        ],
        "sadness": [
            ["Emotional Wellness Toolkit", "https://www.nih.gov/health-information/emotional-wellness-toolkit"],
            ["Dealing with Anxiety", "https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety"],
            ["Relaxation Video", "https://youtu.be/-e-4Kx5px_I"],
        ],
        "surprise": [
            ["Managing Stress", "https://www.health.harvard.edu/health-a-to-z"],
            ["Coping Strategies", "https://www.helpguide.org/mental-health/anxiety/tips-for-dealing-with-anxiety"],
            ["Relaxation Video", "https://youtu.be/m1vaUGtyo-A"],
        ],
    }
    
    # Format the output to include HTML anchor tags
    formatted_suggestions = [
        [title, f'<a href="{link}" target="_blank">{link}</a>'] for title, link in suggestions.get(emotion_key, [["No specific suggestions available.", "#"]])
    ]

    return formatted_suggestions

def get_health_professionals_and_map(location, query):
    """Search nearby healthcare professionals using Google Maps API."""
    try:
        if not location or not query:
            return [], ""  # Return empty list if inputs are missing

        geo_location = gmaps.geocode(location)
        if geo_location:
            lat, lng = geo_location[0]["geometry"]["location"].values()
            places_result = gmaps.places_nearby(location=(lat, lng), radius=10000, keyword=query)["results"]
            professionals = []
            map_ = folium.Map(location=(lat, lng), zoom_start=13)
            for place in places_result:
                # Use a list of values to append each professional
                professionals.append([place['name'], place.get('vicinity', 'No address provided')])
                folium.Marker(
                    location=[place["geometry"]["location"]["lat"], place["geometry"]["location"]["lng"]],
                    popup=f"{place['name']}"
                ).add_to(map_)
            return professionals, map_._repr_html_()

        return [], ""  # Return empty list if no professionals found
    except Exception as e:
        return [], ""  # Return empty list on exception

# Main Application Logic
def app_function(user_input, location, query, history):
    chatbot_history, _ = generate_chatbot_response(user_input, history)
    sentiment_result = analyze_sentiment(user_input)
    emotion_result, cleaned_emotion = detect_emotion(user_input)
    suggestions = generate_suggestions(cleaned_emotion)
    professionals, map_html = get_health_professionals_and_map(location, query)
    disease_result = disease_prediction(user_input)  # Get disease prediction
    return chatbot_history, sentiment_result, emotion_result, suggestions, professionals, map_html, disease_result

# CSS Styling
custom_css = """
body {
    font-family: 'Roboto', sans-serif;
    background-color: #3c6487; /* Set the background color */
    color: white;
}

h1 {
    background: #ffffff;
    color: #000000;
    border-radius: 8px;
    padding: 10px;
    font-weight: bold;
    text-align: center;
    font-size: 2.5rem;
}

textarea, input {
    background: transparent;
    color: black;
    border: 2px solid orange;
    padding: 8px;
    font-size: 1rem;
    caret-color: black;
    outline: none;
    border-radius: 8px;
}

textarea:focus, input:focus {
    background: transparent;
    color: black;
    border: 2px solid orange;
    outline: none;
}

textarea:hover, input:hover {
    background: transparent;
    color: black;
    border: 2px solid orange;
}

.df-container {
    background: white;
    color: black;
    border: 2px solid orange;
    border-radius: 10px;
    padding: 10px;
    font-size: 14px;
    max-height: 400px;
    height: auto;
    overflow-y: auto;
}

#suggestions-title {
    text-align: center !important; /* Ensure the centering is applied */
    font-weight: bold !important; /* Ensure bold is applied */
    color: white !important; /* Ensure color is applied */
    font-size: 4.2rem !important; /* Ensure font size is applied */
    margin-bottom: 20px !important; /* Ensure margin is applied */
}

/* Style for the submit button */
.gr-button {
    background-color: #ae1c93;  /* Set the background color to #ae1c93 */
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06);
    transition: background-color 0.3s ease;
}

.gr-button:hover {
    background-color: #8f167b;
}

.gr-button:active {
    background-color: #7f156b;
}
"""

# Gradio Application
with gr.Blocks(css=custom_css) as app:
    gr.HTML("<h1>🌟 Well-Being Companion</h1>")
    with gr.Row():
        user_input = gr.Textbox(label="Please Enter Your Message Here")
        location = gr.Textbox(label="Please Enter Your Current Location Here")
        query = gr.Textbox(label="Please Enter Which Health Professional You Want To Search Nearby")
        
    submit = gr.Button(value="Submit", variant="primary")

    chatbot = gr.Chatbot(label="Chat History")
    sentiment = gr.Textbox(label="Detected Sentiment")
    emotion = gr.Textbox(label="Detected Emotion")
    
    # Adding Suggestions Title with Styled Markdown (Centered and Bold)
    gr.Markdown("Suggestions", elem_id="suggestions-title")
    
    suggestions = gr.DataFrame(headers=["Title", "Link"])  # Table for suggestions
    professionals = gr.DataFrame(label="Nearby Health Professionals", headers=["Name", "Address"])  # Changed to DataFrame
    map_html = gr.HTML(label="Interactive Map")
    
    disease = gr.Textbox(label="Predicted Disease")  # Display disease prediction

    submit.click(
        app_function,
        inputs=[user_input, location, query, chatbot],
        outputs=[chatbot, sentiment, emotion, suggestions, professionals, map_html, disease],
    )

app.launch()
import gradio as gr
import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score

# Load datasets
def load_data():
    df = pd.read_csv("Training.csv")
    tr = pd.read_csv("Testing.csv")
    
    # Encode diseases
    disease_dict = {
        'Fungal infection': 0, 'Allergy': 1, 'GERD': 2, 'Chronic cholestasis': 3, 'Drug Reaction': 4,
        'Peptic ulcer diseae': 5, 'AIDS': 6, 'Diabetes ': 7, 'Gastroenteritis': 8, 'Bronchial Asthma': 9,
        'Hypertension ': 10, 'Migraine': 11, 'Cervical spondylosis': 12, 'Paralysis (brain hemorrhage)': 13,
        'Jaundice': 14, 'Malaria': 15, 'Chicken pox': 16, 'Dengue': 17, 'Typhoid': 18, 'hepatitis A': 19,
        'Hepatitis B': 20, 'Hepatitis C': 21, 'Hepatitis D': 22, 'Hepatitis E': 23, 'Alcoholic hepatitis': 24,
        'Tuberculosis': 25, 'Common Cold': 26, 'Pneumonia': 27, 'Dimorphic hemmorhoids(piles)': 28,
        'Heart attack': 29, 'Varicose veins': 30, 'Hypothyroidism': 31, 'Hyperthyroidism': 32,
        'Hypoglycemia': 33, 'Osteoarthristis': 34, 'Arthritis': 35,
        '(vertigo) Paroymsal  Positional Vertigo': 36, 'Acne': 37, 'Urinary tract infection': 38,
        'Psoriasis': 39, 'Impetigo': 40
    }

    df.replace({'prognosis': disease_dict}, inplace=True)
    df = df.infer_objects(copy=False)

    tr.replace({'prognosis': disease_dict}, inplace=True)
    tr = tr.infer_objects(copy=False)
    
    return df, tr, disease_dict

try:
    df, tr, disease_dict = load_data()
except FileNotFoundError as e:
    raise RuntimeError("Data files not found. Please ensure `Training.csv` and `Testing.csv` are available.")
except Exception as e:
    raise RuntimeError(f"An error occurred while loading data: {e}")

l1 = list(df.columns[:-1])  
X = df[l1]
y = df['prognosis']
X_test = tr[l1]
y_test = tr['prognosis']

# Trained models
def train_models():
    models = {
        "Decision Tree": DecisionTreeClassifier(),
        "Random Forest": RandomForestClassifier(),
        "Naive Bayes": GaussianNB()
    }
    trained_models = {}
    for model_name, model_obj in models.items():
        model_obj.fit(X, y)
        acc = accuracy_score(y_test, model_obj.predict(X_test))
        trained_models[model_name] = (model_obj, acc)
    return trained_models

trained_models = train_models()

def predict_disease(model, symptoms):
    input_test = np.zeros(len(l1))
    for symptom in symptoms:
        if symptom in l1:
            input_test[l1.index(symptom)] = 1
    prediction = model.predict([input_test])[0]
    return list(disease_dict.keys())[list(disease_dict.values()).index(prediction)]

# Gradio Interface
def app_function(name, symptom1, symptom2, symptom3, symptom4, symptom5):
    if not name.strip():
        return "Please enter the patient's name."
    
    symptoms_selected = [s for s in [symptom1, symptom2, symptom3, symptom4, symptom5] if s != "None"]
    
    if len(symptoms_selected) < 3:
        return "Please select at least 3 symptoms for accurate prediction."
    
    results = []
    for model_name, (model, acc) in trained_models.items():
        prediction = predict_disease(model, symptoms_selected)
        result = f"{model_name} Prediction: Predicted Disease: **{prediction}**"
        result += f" (Accuracy: {acc * 100:.2f}%)"
        results.append(result)
    
    return "\n\n".join(results)

# Gradio Interface Setup
iface = gr.Interface(
    fn=app_function,
    inputs=[
        gr.Textbox(label="Name of Patient"),
        gr.Dropdown(["None"] + l1, label="Symptom 1"),
        gr.Dropdown(["None"] + l1, label="Symptom 2"),
        gr.Dropdown(["None"] + l1, label="Symptom 3"),
        gr.Dropdown(["None"] + l1, label="Symptom 4"),
        gr.Dropdown(["None"] + l1, label="Symptom 5"),
    ],
    outputs=gr.Textbox(label="Prediction"),
    title="Disease Predictor Using Machine Learning",
    description="For accurate results, please select at least 3 symptoms.",
    article="**Caution:** This system is designed for informational purposes only. Please visit a healthcare provider for any medical concerns."
)

# Launch the Gradio application
iface.launch() can you put these in one script  and share the full updated code to run on hugging face space