import os
import cv2
import numpy as np
import mediapipe as mp
import tensorflow as tf
import gradio as gr
import pandas as pd
import random
import sqlite3
import hashlib
import time
from datetime import datetime
from typing import Tuple, List, Dict, Optional

# Set random seeds for reproducibility
np.random.seed(42)
random.seed(42)
tf.random.set_seed(42)

# Disable OneDNN optimization for consistent behavior
os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"

# Initialize the database
def init_db():
    conn = sqlite3.connect('emotion_music_app.db')
    c = conn.cursor()
    
    # Create users table
    c.execute('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        username TEXT UNIQUE NOT NULL,
        password_hash TEXT NOT NULL,
        is_admin INTEGER DEFAULT 0,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
    ''')
    
    # Create history table for emotion detections
    c.execute('''
    CREATE TABLE IF NOT EXISTS detection_history (
        id INTEGER PRIMARY KEY,
        user_id INTEGER NOT NULL,
        emotion TEXT NOT NULL,
        confidence REAL NOT NULL,
        source TEXT NOT NULL,
        detected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (user_id) REFERENCES users (id)
    )
    ''')
    
    # Create music recommendations table
    c.execute('''
    CREATE TABLE IF NOT EXISTS music_recommendations (
        id INTEGER PRIMARY KEY,
        emotion TEXT NOT NULL,
        song_title TEXT NOT NULL,
        artist TEXT NOT NULL,
        link TEXT
    )
    ''')
    
    # Add initial admin user if not exists
    c.execute("SELECT * FROM users WHERE username = 'admin'")
    if not c.fetchone():
        admin_pass = hashlib.sha256("admin123".encode()).hexdigest()
        c.execute("INSERT INTO users (username, password_hash, is_admin) VALUES (?, ?, 1)", 
                 ("admin", admin_pass))
    
    # Sample music recommendations for each emotion
    music_data = [
        # Happy
        ('happy', 'Happy', 'Pharrell Williams', 'https://www.youtube.com/watch?v=ZbZSe6N_BXs'),
        ('happy', "Can't Stop the Feeling", 'Justin Timberlake', 'https://www.youtube.com/watch?v=ru0K8uYEZWw'),
        ('happy', 'Uptown Funk', 'Mark Ronson ft. Bruno Mars', 'https://www.youtube.com/watch?v=OPf0YbXqDm0'),
        
        # Sad
        ('sad', 'Someone Like You', 'Adele', 'https://www.youtube.com/watch?v=hLQl3WQQoQ0'),
        ('sad', 'Hurt', 'Johnny Cash', 'https://www.youtube.com/watch?v=8AHCfZTRGiI'),
        ('sad', 'Fix You', 'Coldplay', 'https://www.youtube.com/watch?v=k4V3Mo61fJM'),
        
        # Angry
        ('angry', 'Killing In The Name', 'Rage Against The Machine', 'https://www.youtube.com/watch?v=bWXazVhlyxQ'),
        ('angry', 'Break Stuff', 'Limp Bizkit', 'https://www.youtube.com/watch?v=ZpUYjpKg9KY'),
        ('angry', 'Master of Puppets', 'Metallica', 'https://www.youtube.com/watch?v=0obBdrfUMzU'),
        
        # Neutral
        ('neutral', 'Weightless', 'Marconi Union', 'https://www.youtube.com/watch?v=UfcAVejslrU'),
        ('neutral', 'Breathe', 'Télépopmusik', 'https://www.youtube.com/watch?v=vyut3GyQtn0'),
        ('neutral', 'Intro', 'The xx', 'https://www.youtube.com/watch?v=3gxNW2Ulpwk'),
        
        # Surprise
        ('surprise', 'Harder Better Faster Stronger', 'Daft Punk', 'https://www.youtube.com/watch?v=gAjR4_CbPpQ'),
        ('surprise', 'Feel Good Inc', 'Gorillaz', 'https://www.youtube.com/watch?v=HyHNuVaZJ-k'),
        ('surprise', 'Pompeii', 'Bastille', 'https://www.youtube.com/watch?v=F90Cw4l-8NY'),
        
        # Fear
        ('fear', 'Lacrimosa', 'Mozart', 'https://www.youtube.com/watch?v=k1-TrAvp_xs'),
        ('fear', 'The Sound of Silence', 'Disturbed', 'https://www.youtube.com/watch?v=u9Dg-g7t2l4'),
        ('fear', 'Everybody Wants To Rule The World', 'Lorde', 'https://www.youtube.com/watch?v=DaVA6sgOpws'),
        
        # Disgust
        ('disgust', 'Creep', 'Radiohead', 'https://www.youtube.com/watch?v=XFkzRNyygfk'),
        ('disgust', 'Lithium', 'Nirvana', 'https://www.youtube.com/watch?v=pkcJEvMcnEg'),
        ('disgust', 'Black Hole Sun', 'Soundgarden', 'https://www.youtube.com/watch?v=3mbBbFH9fAg')
    ]
    
    # Add sample music if table is empty
    c.execute("SELECT COUNT(*) FROM music_recommendations")
    if c.fetchone()[0] == 0:
        c.executemany(
            "INSERT INTO music_recommendations (emotion, song_title, artist, link) VALUES (?, ?, ?, ?)",
            music_data
        )
    
    conn.commit()
    conn.close()

# Authentication functions
def hash_password(password: str) -> str:
    """Create a SHA-256 hash of the password"""
    return hashlib.sha256(password.encode()).hexdigest()

def verify_user(username: str, password: str) -> Tuple[bool, bool, int]:
    """Verify user credentials and return (success, is_admin, user_id)"""
    conn = sqlite3.connect('emotion_music_app.db')
    c = conn.cursor()
    c.execute("SELECT id, password_hash, is_admin FROM users WHERE username = ?", (username,))
    result = c.fetchone()
    conn.close()
    
    if result and result[1] == hash_password(password):
        return True, bool(result[2]), result[0]
    return False, False, -1

def register_user(username: str, password: str) -> Tuple[bool, str]:
    """Register a new user"""
    if len(username) < 3 or len(password) < 6:
        return False, "Username must be at least 3 characters and password must be at least 6 characters"
    
    try:
        conn = sqlite3.connect('emotion_music_app.db')
        c = conn.cursor()
        c.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)", 
                 (username, hash_password(password)))
        conn.commit()
        conn.close()
        return True, "Registration successful!"
    except sqlite3.IntegrityError:
        return False, "Username already exists!"
    except Exception as e:
        return False, f"Registration failed: {str(e)}"

# MediaPipe and Model Functions
def normalize_landmarks(landmarks):
    """Normalize landmarks to be invariant to scale and translation"""
    if not landmarks:
        return [0.0] * 42  # Default 42 values (21 landmarks × 2 coordinates)
    
    # Get bounding box
    xs = [landmark.x for landmark in landmarks.landmark]
    ys = [landmark.y for landmark in landmarks.landmark]
    xmin, xmax = min(xs), max(xs)
    ymin, ymax = min(ys), max(ys)
    
    # Normalize
    width = xmax - xmin
    height = ymax - ymin
    if width == 0: width = 1.0
    if height == 0: height = 1.0
    
    normalized = []
    for landmark in landmarks.landmark:
        normalized.append((landmark.x - xmin) / width)
        normalized.append((landmark.y - ymin) / height)
    
    return normalized

def process_landmarks(landmarks, reference_landmark=None):
    """Process landmarks with reference point or just normalize if no reference"""
    if landmarks:
        if reference_landmark:
            # Use reference point method
            lst = []
            for lm in landmarks.landmark:
                lst.append(lm.x - reference_landmark.x)
                lst.append(lm.y - reference_landmark.y)
            return lst
        else:
            # Use normalization method
            return normalize_landmarks(landmarks)
    else:
        return [0.0] * 42  # Default size for empty landmarks

def prepare_input_features(face_landmarks, left_hand_landmarks, right_hand_landmarks):
    """Prepare and properly format input features for model prediction"""
    # Process each landmark set
    face_features = process_landmarks(face_landmarks, 
                                     face_landmarks.landmark[1] if face_landmarks else None)
    
    left_hand_features = process_landmarks(left_hand_landmarks,
                                         left_hand_landmarks.landmark[8] if left_hand_landmarks else None)
    
    right_hand_features = process_landmarks(right_hand_landmarks,
                                          right_hand_landmarks.landmark[8] if right_hand_landmarks else None)
    
    # Combine all features
    combined_features = face_features + left_hand_features + right_hand_features
    
    # Ensure exact size matching with model input (1020)
    if len(combined_features) < 1020:
        combined_features = np.pad(combined_features, (0, 1020 - len(combined_features)), 'constant')
    elif len(combined_features) > 1020:
        combined_features = combined_features[:1020]
    
    # Reshape to match model's expected input
    return np.array(combined_features).reshape(1, 1020).astype(np.float32)

def load_emotion_model():
    """Load the model and labels"""
    # Try to load the model from different paths based on Colab environment
    try:
        # Try default path first
        model = tf.keras.models.load_model("model.h5")
        label = np.load("labels.npy")
    except:
        try:
            # Try Google Drive path
            model = tf.keras.models.load_model("/content/drive/MyDrive/face_emotion_based_music_rec/model.h5")
            label = np.load("/content/drive/MyDrive/face_emotion_based_music_rec/labels.npy")
        except:
            # If both fail, create dummy model and labels for demo purposes
            print("Warning: Using dummy model for demonstration")
            inputs = tf.keras.layers.Input((1020,))
            x = tf.keras.layers.Dense(128, activation='relu')(inputs)
            outputs = tf.keras.layers.Dense(7, activation='softmax')(x)
            model = tf.keras.Model(inputs, outputs)
            label = np.array(['happy', 'sad', 'angry', 'neutral', 'surprise', 'fear', 'disgust'])
    
    return model, label

# Global variables
model, labels = load_emotion_model()
mp_holistic = mp.solutions.holistic
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
holistic = mp_holistic.Holistic(min_detection_confidence=0.5, min_tracking_confidence=0.5)

def process_image(image, user_id=None, source="upload"):
    """Process image and return emotion prediction with visualization"""
    if image is None:
        return None, "No image provided", None, None
    
    # If image is a file path, load it
    if isinstance(image, str):
        image = cv2.imread(image)
        if image is None:
            return None, "Failed to load image", None, None
    
    # Convert to RGB for MediaPipe
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    # Process with MediaPipe
    results = holistic.process(image_rgb)
    
    # Prepare features
    features = prepare_input_features(
        results.face_landmarks,
        results.left_hand_landmarks,
        results.right_hand_landmarks
    )
    
    # Make prediction
    prediction = model.predict(features, verbose=0)
    predicted_label = labels[np.argmax(prediction)]
    prediction_confidence = float(np.max(prediction))
    
    # Visualize results
    output_image = image.copy()
    
    # Add prediction text
    cv2.putText(
        output_image, 
        f"{predicted_label} ({prediction_confidence:.2f})", 
        (50, 50), 
        cv2.FONT_HERSHEY_SIMPLEX, 
        1, 
        (0, 0, 255), 
        2
    )
    
    # Draw landmarks
    if results.face_landmarks:
        mp_drawing.draw_landmarks(
            output_image, 
            results.face_landmarks, 
            mp_holistic.FACEMESH_TESSELATION,
            mp_drawing.DrawingSpec(color=(80, 110, 10), thickness=1, circle_radius=1),
            mp_drawing.DrawingSpec(color=(80, 256, 121), thickness=1, circle_radius=1)
        )
    
    if results.left_hand_landmarks:
        mp_drawing.draw_landmarks(
            output_image, 
            results.left_hand_landmarks, 
            mp_hands.HAND_CONNECTIONS,
            mp_drawing.DrawingSpec(color=(121, 22, 76), thickness=2, circle_radius=4),
            mp_drawing.DrawingSpec(color=(121, 44, 250), thickness=2, circle_radius=2)
        )
    
    if results.right_hand_landmarks:
        mp_drawing.draw_landmarks(
            output_image, 
            results.right_hand_landmarks, 
            mp_hands.HAND_CONNECTIONS,
            mp_drawing.DrawingSpec(color=(245, 117, 66), thickness=2, circle_radius=4),
            mp_drawing.DrawingSpec(color=(245, 66, 230), thickness=2, circle_radius=2)
        )
    
    # Convert output image back to RGB for Gradio
    output_image = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
    
    # Save detection to history if user is logged in
    if user_id is not None:
        conn = sqlite3.connect('emotion_music_app.db')
        c = conn.cursor()
        c.execute(
            "INSERT INTO detection_history (user_id, emotion, confidence, source) VALUES (?, ?, ?, ?)",
            (user_id, predicted_label, prediction_confidence, source)
        )
        conn.commit()
        conn.close()
    
    # Get music recommendations
    music_recs = get_music_recommendations(predicted_label)
    
    return output_image, f"Detected emotion: {predicted_label} ({prediction_confidence:.4f})", predicted_label, music_recs

def get_music_recommendations(emotion):
    """Get music recommendations for a detected emotion"""
    conn = sqlite3.connect('emotion_music_app.db')
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute("SELECT song_title, artist, link FROM music_recommendations WHERE emotion = ?", (emotion,))
    recommendations = [dict(row) for row in c.fetchall()]
    conn.close()
    
    if not recommendations:
        # Fallback if no recommendations found
        return [{"song_title": "No specific recommendations", "artist": "Try our general playlist", "link": "#"}]
    
    return recommendations

def webcam_prediction(image, user_id=None):
    """Process webcam frame for emotion detection"""
    if image is None:
        return None, "No webcam feed available", None
    
    result_image, result_text, emotion, music_recs = process_image(image, user_id, source="webcam")
    
    if music_recs:
        music_html = "<h3>Music Recommendations:</h3><ul>"
        for rec in music_recs[:3]:  # Show top 3 recommendations
            music_html += f"<li><a href='{rec['link']}' target='_blank'>{rec['song_title']} by {rec['artist']}</a></li>"
        music_html += "</ul>"
    else:
        music_html = "<p>No music recommendations available for this emotion.</p>"
    
    return result_image, result_text, music_html

def upload_prediction(image, user_id=None):
    """Process uploaded image for emotion detection"""
    if image is None:
        return None, "Please upload an image", None
    
    # Convert to OpenCV format
    image_cv = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
    
    result_image, result_text, emotion, music_recs = process_image(image_cv, user_id, source="upload")
    
    if music_recs:
        music_html = "<h3>Music Recommendations:</h3><ul>"
        for rec in music_recs[:3]:  # Show top 3 recommendations
            music_html += f"<li><a href='{rec['link']}' target='_blank'>{rec['song_title']} by {rec['artist']}</a></li>"
        music_html += "</ul>"
    else:
        music_html = "<p>No music recommendations available for this emotion.</p>"
    
    return result_image, result_text, music_html

# Admin Functions
def get_all_users():
    """Get all users for admin panel"""
    conn = sqlite3.connect('emotion_music_app.db')
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute("SELECT id, username, is_admin, created_at FROM users ORDER BY id")
    users = [dict(row) for row in c.fetchall()]
    conn.close()
    return users

def get_detection_history(user_id=None, limit=100):
    """Get detection history for admin panel or specific user"""
    conn = sqlite3.connect('emotion_music_app.db')
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    
    if user_id is None:
        # For admin - get all history with usernames
        c.execute("""
            SELECT d.id, u.username, d.emotion, d.confidence, d.source, d.detected_at 
            FROM detection_history d
            JOIN users u ON d.user_id = u.id
            ORDER BY d.detected_at DESC
            LIMIT ?
        """, (limit,))
    else:
        # For specific user
        c.execute("""
            SELECT id, emotion, confidence, source, detected_at 
            FROM detection_history
            WHERE user_id = ?
            ORDER BY detected_at DESC
            LIMIT ?
        """, (user_id, limit))
    
    history = [dict(row) for row in c.fetchall()]
    conn.close()
    return history

def get_music_data():
    """Get all music recommendations for admin panel"""
    conn = sqlite3.connect('emotion_music_app.db')
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute("SELECT id, emotion, song_title, artist, link FROM music_recommendations ORDER BY emotion, id")
    music_data = [dict(row) for row in c.fetchall()]
    conn.close()
    return music_data

def add_music_recommendation(emotion, song_title, artist, link):
    """Add new music recommendation"""
    try:
        conn = sqlite3.connect('emotion_music_app.db')
        c = conn.cursor()
        c.execute(
            "INSERT INTO music_recommendations (emotion, song_title, artist, link) VALUES (?, ?, ?, ?)",
            (emotion, song_title, artist, link)
        )
        conn.commit()
        conn.close()
        return True, "Music recommendation added successfully!"
    except Exception as e:
        return False, f"Failed to add music recommendation: {str(e)}"

def delete_music(music_id):
    """Delete a music recommendation"""
    try:
        conn = sqlite3.connect('emotion_music_app.db')
        c = conn.cursor()
        c.execute("DELETE FROM music_recommendations WHERE id = ?", (music_id,))
        conn.commit()
        conn.close()
        return True, f"Music ID {music_id} deleted successfully"
    except Exception as e:
        return False, f"Failed to delete music: {str(e)}"

def toggle_admin(user_id):
    """Toggle admin status for user"""
    try:
        conn = sqlite3.connect('emotion_music_app.db')
        c = conn.cursor()
        c.execute("SELECT is_admin FROM users WHERE id = ?", (user_id,))
        current_status = c.fetchone()[0]
        new_status = 0 if current_status else 1
        c.execute("UPDATE users SET is_admin = ? WHERE id = ?", (new_status, user_id))
        conn.commit()
        conn.close()
        return True, f"User ID {user_id} admin status updated"
    except Exception as e:
        return False, f"Failed to update admin status: {str(e)}"

def delete_user(user_id):
    """Delete a user and their detection history"""
    try:
        conn = sqlite3.connect('emotion_music_app.db')
        c = conn.cursor()
        # Delete user's detection history first (foreign key constraint)
        c.execute("DELETE FROM detection_history WHERE user_id = ?", (user_id,))
        # Then delete the user
        c.execute("DELETE FROM users WHERE id = ?", (user_id,))
        conn.commit()
        conn.close()
        return True, f"User ID {user_id} deleted successfully"
    except Exception as e:
        return False, f"Failed to delete user: {str(e)}"

# Gradio Interface Setup
def create_gradio_app():
    # Initialize database
    init_db()
    
    # Session state to track login
    class SessionState:
        def __init__(self):
            self.user_id = None
            self.username = None
            self.is_admin = False
            self.login_message = ""
    
    state = SessionState()
    
    # Login component
    def login(username, password):
        success, is_admin, user_id = verify_user(username, password)
        if success:
            state.user_id = user_id
            state.username = username
            state.is_admin = is_admin
            state.login_message = f"Welcome, {username}!"
            return f"Logged in as {username}", gr.update(visible=False), gr.update(visible=True)
        else:
            state.login_message = "Invalid username or password"
            return "Login failed. Please check your credentials.", gr.update(visible=True), gr.update(visible=False)
    
    def register(username, password, confirm_password):
        if password != confirm_password:
            return "Passwords do not match!"
        
        success, message = register_user(username, password)
        return message
    
    def logout():
        state.user_id = None
        state.username = None
        state.is_admin = False
        state.login_message = ""
        return "Logged out", gr.update(visible=True), gr.update(visible=False)
    
    # Wrapper functions for user ID tracking
    def webcam_wrapper(image):
        return webcam_prediction(image, state.user_id)
    
    def upload_wrapper(image):
        return upload_prediction(image, state.user_id)
    
    # Admin functions
    def admin_get_users():
        if not state.is_admin:
            return "Unauthorized access!"
        
        users = get_all_users()
        df = pd.DataFrame(users)
        df['is_admin'] = df['is_admin'].apply(lambda x: "Yes" if x else "No")
        return df
    
    def admin_get_history():
        if not state.is_admin:
            return "Unauthorized access!"
        
        history = get_detection_history()
        return pd.DataFrame(history)
    
    def admin_get_music():
        if not state.is_admin:
            return "Unauthorized access!"
        
        music = get_music_data()
        return pd.DataFrame(music)
    
    def admin_add_music(emotion, song_title, artist, link):
        if not state.is_admin:
            return "Unauthorized access!"
        
        success, message = add_music_recommendation(emotion, song_title, artist, link)
        return message
    
    def admin_delete_music(music_id):
        if not state.is_admin:
            return "Unauthorized access!"
        
        try:
            music_id = int(music_id)
            success, message = delete_music(music_id)
            return message
        except ValueError:
            return "Invalid music ID"
    
    def admin_toggle_user_admin(user_id):
        if not state.is_admin:
            return "Unauthorized access!"
        
        try:
            user_id = int(user_id)
            success, message = toggle_admin(user_id)
            return message
        except ValueError:
            return "Invalid user ID"
    
    def admin_delete_user_account(user_id):
        if not state.is_admin:
            return "Unauthorized access!"
        
        try:
            user_id = int(user_id)
            success, message = delete_user(user_id)
            return message
        except ValueError:
            return "Invalid user ID"
    
    def get_user_history():
        if not state.user_id:
            return "Please log in to view your history"
        
        history = get_detection_history(state.user_id)
        if history:
            return pd.DataFrame(history)
        else:
            return "No detection history yet"
    
    with gr.Blocks(title="Emotion-Based Music Recommendation System") as app:
        # Title and description
        gr.Markdown("# 🎵 Emotion-Based Music Recommendation System")
        gr.Markdown("Detect emotions from webcam or uploaded images and get personalized music recommendations")
        
        # Login/Registration Interface
        with gr.Tab("Login/Register"):
            with gr.Group(visible=True) as login_group:
                gr.Markdown("## Login")
                login_username = gr.Textbox(label="Username")
                login_password = gr.Textbox(label="Password", type="password")
                login_button = gr.Button("Login")
                login_message = gr.Textbox(label="Status", interactive=False)
                
                gr.Markdown("## Register New Account")
                reg_username = gr.Textbox(label="Username")
                reg_password = gr.Textbox(label="Password", type="password")
                reg_confirm = gr.Textbox(label="Confirm Password", type="password")
                reg_button = gr.Button("Register")
                reg_message = gr.Textbox(label="Registration Status", interactive=False)
            
            with gr.Group(visible=False) as user_panel:
                gr.Markdown("## User Panel")
                user_info = gr.Textbox(label="User Info", interactive=False)
                logout_button = gr.Button("Logout")
                
                # User history
                gr.Markdown("### Your Detection History")
                history_button = gr.Button("View My History")
                user_history = gr.DataFrame(label="Your Detection History")
        
        # Main functionality tabs - visible after login
        with gr.Tab("Webcam Detection"):
            with gr.Row():
                with gr.Column():
                    webcam_input = gr.Image(source="webcam", streaming=True, label="Webcam Input")
                    webcam_capture = gr.Button("Capture and Analyze")
                
                with gr.Column():
                    webcam_output = gr.Image(label="Detection Result")
                    webcam_result = gr.Textbox(label="Detected Emotion")
                    webcam_music = gr.HTML(label="Music Recommendations")
        
        with gr.Tab("Image Upload"):
            with gr.Row():
                with gr.Column():
                    upload_input = gr.Image(type="pil", label="Upload Image")
                    upload_button = gr.Button("Analyze Image")
                
                with gr.Column():
                    upload_output = gr.Image(label="Detection Result")
                    upload_result = gr.Textbox(label="Detected Emotion")
                    upload_music = gr.HTML(label="Music Recommendations")
        
        # Admin Panel - only visible to admins
        with gr.Tab("Admin Panel"):
            admin_check = gr.Markdown("### Admin Panel\nOnly accessible by administrators.")
            
            with gr.Tabs():
                with gr.Tab("User Management"):
                    users_refresh = gr.Button("Refresh Users List")
                    users_table = gr.DataFrame(label="Registered Users")
                    
                    with gr.Row():
                        with gr.Column():
                            admin_toggle_id = gr.Textbox(label="User ID to Toggle Admin")
                            admin_toggle_button = gr.Button("Toggle Admin Status")
                            admin_toggle_result = gr.Textbox(label="Result", interactive=False)
                        
                        with gr.Column():
                            user_delete_id = gr.Textbox(label="User ID to Delete")
                            user_delete_button = gr.Button("Delete User")
                            user_delete_result = gr.Textbox(label="Result", interactive=False)
                
                with gr.Tab("Detection History"):
                    history_refresh = gr.Button("Refresh History")
                    history_table = gr.DataFrame(label="All Detection History")
                
                with gr.Tab("Music Management"):
                    music_refresh = gr.Button("Refresh Music List")
                    music_table = gr.DataFrame(label="Music Recommendations")
                    
                    gr.Markdown("### Add New Music Recommendation")
                    with gr.Row():
                        with gr.Column():
                            music_emotion = gr.Dropdown(
                                choices=["happy", "sad", "angry", "neutral", "surprise", "fear", "disgust"],
                                label="Emotion"
                            )
                            music_title = gr.Textbox(label="Song Title")
                        
                        with gr.Column():
                            music_artist = gr.Textbox(label="Artist")
                            music_link = gr.Textbox(label="YouTube or Spotify Link")
                    
                    music_add_button = gr.Button("Add Music")
                    music_add_result = gr.Textbox(label="Result", interactive=False)
                    
                    gr.Markdown("### Delete Music")
                    with gr.Row():
                        music_delete_id = gr.Textbox(label="Music ID to Delete")
                        music_delete_button = gr.Button("Delete Music")


please complete this code