import gradio as gr
import pandas as pd
import json
from datetime import datetime
import asyncio
from threading import Thread
import time
import traceback

# Import your existing modules
from rag_review import build_developer_agent_graph
from tools import (
    get_app_changelog_versions, 
    save_app_info_raw_text, 
    initialize_absa_model,
    scrape_english_reviews_with_aspects
)
from model_loader import model_manager

class GradioAppAnalyzer:
    def __init__(self):
        self.graph = None
        self.current_app_id = None
        self.available_versions = []
        self.model_loaded = False
        self.chat_history = []
        self.app_title = ""
        
    def initialize_system(self):
        """Initialize the analysis system"""
        try:
            print("🚀 Initializing ABSA model...")
            self.model_loaded = initialize_absa_model()
            
            if self.model_loaded:
                self.graph = build_developer_agent_graph()
                return "✅ System initialized successfully! Ready to analyze apps."
            else:
                return "❌ Failed to load ABSA model. Please check the setup."
        except Exception as e:
            print(f"Initialization error: {e}")
            traceback.print_exc()
            return f"❌ Initialization error: {str(e)}"
    
    def load_app_versions(self, app_id):
        """Load available versions for the given app ID"""
        if not app_id or app_id.strip() == "":
            return (
                gr.update(choices=["Latest 5 versions"], value="Latest 5 versions"), 
                "❌ Please enter a valid app ID", 
                "No app loaded"
            )
        
        try:
            # Clean and set the app ID
            clean_app_id = app_id.strip()
            self.current_app_id = clean_app_id
            
            print(f"📱 Loading app: {clean_app_id}")
            
            # Step 1: Get app info first
            try:
                print(f"📱 Getting app info for {clean_app_id}...")
                app_info = save_app_info_raw_text(clean_app_id)
                
                if app_info and "Title:" in app_info:
                    # Extract title from app info
                    lines = app_info.split('\n')
                    title_line = next((line for line in lines if line.startswith('Title:')), None)
                    if title_line:
                        self.app_title = title_line.replace('Title: ', '').strip()
                    else:
                        self.app_title = f"App: {clean_app_id}"
                else:
                    self.app_title = f"App: {clean_app_id}"
                    print(f"⚠️ Could not get full app info for {clean_app_id}")
                    
            except Exception as e:
                print(f"⚠️ App info error: {e}")
                self.app_title = f"App: {clean_app_id}"
            
            # Step 2: Get available versions
            try:
                print(f"📱 Fetching versions for {clean_app_id}...")
                versions = get_app_changelog_versions(clean_app_id)
                
                if versions and len(versions) > 0:
                    # Clean and validate versions
                    clean_versions = []
                    for v in versions:
                        if v and isinstance(v, str) and v.strip():
                            clean_versions.append(v.strip())
                    
                    if clean_versions:
                        self.available_versions = clean_versions
                        print(f"✅ Found {len(clean_versions)} versions: {clean_versions[:5]}...")
                        
                        # Prepare dropdown options (limit to top 15 for UI)
                        version_options = ["Latest 5 versions"] + clean_versions[:15]
                        
                        status_msg = f"✅ Loaded {self.app_title} - Found {len(clean_versions)} versions"
                        
                        return (
                            gr.update(choices=version_options, value="Latest 5 versions"),
                            status_msg,
                            self.app_title
                        )
                    else:
                        raise ValueError("No valid versions found")
                else:
                    raise ValueError("No versions returned")
                    
            except Exception as e:
                print(f"⚠️ Version fetch error: {e}")
                # Use fallback versions based on common version patterns
                fallback_versions = [
                    "1.0.0", "1.0.1", "1.0.2", "1.1.0", "1.1.1",
                    "2.0.0", "2.0.1", "2.1.0", "3.0.0", "3.0.1"
                ]
                self.available_versions = fallback_versions
                
                version_options = ["Latest 5 versions"] + fallback_versions
                status_msg = f"⚠️ Loaded {self.app_title} - Using fallback versions (version scraping failed)"
                
                return (
                    gr.update(choices=version_options, value="Latest 5 versions"),
                    status_msg,
                    self.app_title
                )
                
        except Exception as e:
            error_msg = f"❌ Error loading app {app_id}: {str(e)}"
            print(error_msg)
            traceback.print_exc()
            
            # Reset state on error
            self.current_app_id = None
            self.available_versions = []
            self.app_title = "No app loaded"
            
            return (
                gr.update(choices=["Latest 5 versions"], value="Latest 5 versions"),
                error_msg,
                "No app loaded"
            )
    
    def process_query(self, message, history, selected_version):
        """Process user query and return response"""
        if not self.model_loaded:
            return history + [[message, "❌ System not initialized. Please click 'Initialize System' first."]]
        
        if not self.current_app_id:
            return history + [[message, "❌ Please load an app first by entering an App ID and clicking 'Load App & Versions'."]]
        
        if not message or not message.strip():
            return history
        
        try:
            print(f"🔄 Processing query: '{message}' for app: {self.current_app_id}")
            
            # Prepare state for the graph
            state = {
                "messages": [{"role": "user", "content": message.strip()}],
                "query_type": None,
                "raw_query": message.strip(),
                "aspect": None,
                "version": selected_version if selected_version != "Latest 5 versions" else None,  # Pass the selected version
                "app_ids": [self.current_app_id],  # Use the loaded app ID
                "reviews": None,
                "app_info": None,
                "recent_changes": None,
                "filtered_reviews": None,
                "absa_results": None,
                "negative_aspects": None,
                "problems": None,
                "solutions": None,
                "final_response": None,
                "review_text": None,
                "conversation_context": None
            }
            
            print(f"📱 State setup - App ID: {self.current_app_id}, Version: {state['version']}")
            
            # Run the graph
            print(f"🔄 Running analysis graph...")
            result = self.graph.invoke(state)
            
            # Get response
            final_response = result.get("final_response", "Sorry, I couldn't process your request. Please try again.")
            
            # Add metadata to response
            response_with_meta = f"{final_response}\n\n---\n📱 **App**: {self.app_title}\n🔄 **App ID**: {self.current_app_id}"
            if selected_version and selected_version != "Latest 5 versions":
                response_with_meta += f"\n📋 **Version**: {selected_version}"
            
            # Return updated history
            return history + [[message, response_with_meta]]
            
        except Exception as e:
            error_msg = f"❌ Error processing query: {str(e)}\n\nPlease check:\n1. System is initialized\n2. App is loaded correctly\n3. Query is valid"
            print(f"Process query error: {e}")
            traceback.print_exc()
            return history + [[message, error_msg]]
    
    def clear_chat(self):
        """Clear chat history"""
        self.chat_history = []
        return []
    
    def get_system_status(self):
        """Get current system status"""
        status_parts = []
        
        # Model status
        if self.model_loaded:
            status_parts.append("🟢 ABSA Model: Loaded")
        else:
            status_parts.append("🔴 ABSA Model: Not loaded")
        
        # Graph status
        if self.graph:
            status_parts.append("🟢 Analysis Graph: Ready")
        else:
            status_parts.append("🔴 Analysis Graph: Not ready")
        
        # App status
        if self.current_app_id:
            status_parts.append(f"📱 Current App: {self.app_title}")
            status_parts.append(f"🆔 App ID: {self.current_app_id}")
            status_parts.append(f"📋 Versions Available: {len(self.available_versions)}")
            if self.available_versions:
                status_parts.append(f"📋 Latest Version: {self.available_versions[0]}")
        else:
            status_parts.append("📱 No app loaded")
        
        return "\n".join(status_parts)
    
    def reset_system(self):
        """Reset the entire system"""
        self.current_app_id = None
        self.available_versions = []
        self.app_title = ""
        self.chat_history = []
        return (
            "",  # Clear app ID input
            gr.update(choices=["Latest 5 versions"], value="Latest 5 versions"),  # Reset dropdown
            "System reset - please load an app",  # Status
            "No app loaded",  # App title
            [],  # Clear chat
            self.get_system_status()  # Updated status
        )

# Initialize the analyzer
analyzer = GradioAppAnalyzer()

# Updated CSS (same as before)
custom_css = """
body, .gradio-container {
    margin: 0 !important;
    padding: 0 !important;
    max-width: 100% !important;
    width: 100% !important;
}

.contain {
    max-width: 100% !important;
    margin: 0 !important;
    padding: 20px !important;
}

#title {
    text-align: center;
    background: linear-gradient(90deg, #1e3a8a 0%, #3730a3 100%);
    color: white;
    padding: 25px;
    border-radius: 12px;
    margin-bottom: 25px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

#title h1 {
    margin: 0 0 10px 0;
    font-size: 2.5em;
}

#status-box {
    background: #f8fafc;
    border-radius: 8px;
    padding: 15px;
    border-left: 4px solid #2563eb;
    margin: 5px 0;
}

#app-info-box {
    background: #f0fdf4;
    border-radius: 8px;
    padding: 15px;
    border-left: 4px solid #16a34a;
    margin: 5px 0;
}

#error-box {
    background: #fef2f2;
    border-radius: 8px;
    padding: 15px;
    border-left: 4px solid #dc2626;
    margin: 5px 0;
}

#chat-container {
    height: 650px;
    border-radius: 12px;
    border: 1px solid #e5e7eb;
}

#query-examples {
    background: #fffbeb;
    border-radius: 10px;
    padding: 15px;
    margin: 15px 0;
    border-left: 4px solid #f59e0b;
}

.sidebar-group {
    background: #ffffff;
    border-radius: 10px;
    padding: 15px;
    margin: 10px 0;
    border: 1px solid #e5e7eb;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.main-container {
    width: 100% !important;
    max-width: 100% !important;
    padding: 0 !important;
    margin: 0 !important;
}

.left-column {
    min-width: 350px !important;
    max-width: 400px !important;
}

.right-column {
    flex: 1 !important;
    min-width: 700px !important;
}

.input-group {
    margin: 10px 0;
}

.status-text {
    font-family: 'Monaco', 'Consolas', monospace;
    font-size: 0.9em;
}
"""

# Create Gradio interface
def create_interface():
    with gr.Blocks(
        css=custom_css, 
        title="App Review Analyzer",
        theme=gr.themes.Soft(primary_hue="blue", secondary_hue="gray")
    ) as demo:
        
        # Title and description
        gr.HTML("""
        <div id="title">
            <h1>🔍 App Review Analyzer</h1>
            <p style="font-size: 1.2em; margin: 10px 0;">AI-powered analysis of app reviews using ABSA (Aspect-Based Sentiment Analysis)</p>
            <p style="font-size: 1em; opacity: 0.9;"><em>Thesis Project - Advanced Review Analytics System</em></p>
        </div>
        """)
        
        # Main layout - full width
        with gr.Row(elem_classes=["main-container"]):
            # Left sidebar - App configuration
            with gr.Column(scale=1, elem_classes=["left-column"]):
                gr.HTML("<h2 style='text-align: center; color: #1e40af; margin-bottom: 20px;'>📱 Configuration</h2>")
                
                # System initialization
                with gr.Group(elem_classes=["sidebar-group"]):
                    gr.HTML("<h3 style='margin-top: 0;'>🚀 System Setup</h3>")
                    init_btn = gr.Button("🚀 Initialize System", variant="primary", size="lg")
                    init_status = gr.Textbox(
                        label="Status",
                        value="Click 'Initialize System' to start",
                        interactive=False,
                        elem_id="status-box",
                        elem_classes=["status-text"]
                    )
                
                # App ID input
                with gr.Group(elem_classes=["sidebar-group"]):
                    gr.HTML("<h3 style='margin-top: 0;'>📲 App Selection</h3>")
                    
                    # Add examples dropdown for common apps
                    gr.HTML("<p><strong>Popular Apps:</strong></p>")
                    example_apps = gr.Dropdown(
                        label="Choose Example App",
                        choices=[
                            "com.a10minuteschool.tenminuteschool (10 Minute School)",
                            "com.facebook.android (Facebook)",
                            "com.instagram.android (Instagram)", 
                            "com.whatsapp (WhatsApp)",
                            "com.google.android.youtube (YouTube)",
                            "com.spotify.music (Spotify)",
                            "com.netflix.mediaclient (Netflix)"
                        ],
                        value=None,
                        allow_custom_value=False
                    )
                    
                    app_id_input = gr.Textbox(
                        label="App ID (Google Play Store)",
                        placeholder="Enter app package name (e.g., com.example.app)",
                        value="com.a10minuteschool.tenminuteschool",
                        elem_classes=["input-group"]
                    )
                    
                    with gr.Row():
                        load_app_btn = gr.Button("📋 Load App", variant="secondary", size="lg")
                        reset_btn = gr.Button("🔄 Reset", variant="stop", size="sm")
                    
                    app_title = gr.Textbox(
                        label="App Name",
                        value="No app loaded",
                        interactive=False,
                        elem_id="app-info-box",
                        elem_classes=["status-text"]
                    )
                
                # Version selection
                with gr.Group(elem_classes=["sidebar-group"]):
                    gr.HTML("<h3 style='margin-top: 0;'>📋 Version Selection</h3>")
                    version_dropdown = gr.Dropdown(
                        label="Select Version",
                        choices=["Latest 5 versions"],
                        value="Latest 5 versions",
                        info="Choose a specific version or use latest",
                        allow_custom_value=False,
                        elem_classes=["input-group"]
                    )
                    app_status = gr.Textbox(
                        label="Loading Status",
                        value="No app loaded",
                        interactive=False,
                        elem_id="status-box",
                        elem_classes=["status-text"]
                    )
                
                # System status
                with gr.Group(elem_classes=["sidebar-group"]):
                    gr.HTML("<h3 style='margin-top: 0;'>📊 System Status</h3>")
                    system_status = gr.Textbox(
                        label="Current Status",
                        interactive=False,
                        lines=6,
                        elem_id="status-box",
                        elem_classes=["status-text"]
                    )
                    refresh_status_btn = gr.Button("🔄 Refresh Status", size="sm")
            
            # Right side - Chat interface (full width)
            with gr.Column(scale=2, elem_classes=["right-column"]):
                gr.HTML("<h2 style='text-align: center; color: #1e40af; margin-bottom: 20px;'>💬 Analysis Chat</h2>")
                
                # Chat interface
                chatbot = gr.Chatbot(
                    label="🤖 App Review Analysis Assistant",
                    height=650,
                    elem_id="chat-container",
                    show_copy_button=True,
                    show_share_button=False,
                    bubble_full_width=False
                )
                
                # Query input
                with gr.Row():
                    query_input = gr.Textbox(
                        label="Your Query",
                        placeholder="Ask about app issues, versions, aspects, or solutions...",
                        scale=4,
                        lines=2
                    )
                    send_btn = gr.Button("📤 Send", variant="primary", scale=1, size="lg")
                
                # Action buttons
                with gr.Row():
                    clear_btn = gr.Button("🗑️ Clear Chat", variant="secondary")
                    gr.HTML("<div style='flex: 1;'></div>")  # Spacer
                    gr.HTML("<div style='text-align: right; color: #6b7280; font-size: 0.9em;'>Press Enter to send</div>")
                    
                # Query examples
                gr.HTML("""
                <div id="query-examples">
                    <h3 style="margin-top: 0; color: #92400e;">💡 Example Queries</h3>
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
                        <div>
                            <strong>📊 Analysis Queries:</strong>
                            <ul style="margin: 5px 0; color: #000000;">
                                <li style="color: #6b7280;">"What are the main problems in the app?"</li>
                                <li style="color: #6b7280;">"Show me problems and solutions"</li>
                                <li style="color: #6b7280;">"What issues are in version 3.9.8.4?"</li>
                                <li style="color: #6b7280;">"Analyze payment-related reviews"</li>
                            </ul>
                        </div>
                        <div>
                            <strong>🎯 Direct Queries:</strong>
                            <ul style="margin: 5px 0; color: #000000;">
                                <li style="color: #6b7280;">"What are solutions for login issues?"</li>
                                <li style="color: #6b7280;">"Analyze this review: [paste text]"</li>
                                <li style="color: #6b7280;">"Show me reviews for latest version"</li>
                                <li style="color: #6b7280;">"What aspects are users complaining about?"</li>
                            </ul>
                        </div>
                    </div>
                </div>
                """)
        
        # Event handlers
        def init_system():
            return analyzer.initialize_system()
        
        def load_app(app_id):
            return analyzer.load_app_versions(app_id)
        
        def refresh_status():
            return analyzer.get_system_status()
        
        def send_message(message, history, selected_version):
            return analyzer.process_query(message, history, selected_version)
        
        def clear_chat():
            return analyzer.clear_chat()
        
        def reset_system():
            return analyzer.reset_system()
        
        def select_example_app(selected_app):
            if selected_app and "(" in selected_app:
                # Extract app ID from selection
                app_id = selected_app.split("(")[0].strip()
                return app_id
            return ""
        
        # Connect events
        init_btn.click(
            fn=init_system,
            outputs=[init_status],
            show_progress=True
        )
        
        # Example app selection
        example_apps.change(
            fn=select_example_app,
            inputs=[example_apps],
            outputs=[app_id_input]
        )
        
        # Load app
        load_app_btn.click(
            fn=load_app,
            inputs=[app_id_input],
            outputs=[version_dropdown, app_status, app_title],
            show_progress=True
        )
        
        # Reset system
        reset_btn.click(
            fn=reset_system,
            outputs=[app_id_input, version_dropdown, app_status, app_title, chatbot, system_status]
        )
        
        refresh_status_btn.click(
            fn=refresh_status,
            outputs=[system_status]
        )
        
        # Chat functionality
        send_btn.click(
            fn=send_message,
            inputs=[query_input, chatbot, version_dropdown],
            outputs=[chatbot],
            show_progress=True
        ).then(
            lambda: "",  # Clear input after sending
            outputs=[query_input]
        )
        
        # Enter key support
        query_input.submit(
            fn=send_message,
            inputs=[query_input, chatbot, version_dropdown],
            outputs=[chatbot],
            show_progress=True
        ).then(
            lambda: "",
            outputs=[query_input]
        )
        
        clear_btn.click(
            fn=clear_chat,
            outputs=[chatbot]
        )
        
        # Auto-refresh system status on load
        demo.load(
            fn=refresh_status,
            outputs=[system_status]
        )
    
    return demo

# Launch the interface
if __name__ == "__main__":
    # Create and launch the interface
    demo = create_interface()
    
    print("🚀 Starting Gradio App Review Analyzer...")
    print("📱 This interface provides:")
    print("   • App ID and version management")
    print("   • Real-time chat-based analysis") 
    print("   • ABSA-powered review insights")
    print("   • Problem and solution identification")
    print("\n🌐 Interface will be available at: http://localhost:7860")
    
    # Launch with improved settings
    demo.launch(
        share=False,
        debug=True,  # Enable debug for better error tracking
        show_error=True,
        inbrowser=True,  # Automatically open browser
        favicon_path=None,
        ssl_verify=False
    )