import sys
import argparse
import time
from pathlib import Path
from fabriq.rag_pipeline import RAGPipeline
from fabriq.indexing import DocumentIndexer
from fabriq.config_parser import ConfigParser
import threading
import logging

# Silence all logs lower than ERROR
logging.getLogger().setLevel(logging.ERROR)
logging.getLogger("openai").setLevel(logging.ERROR)     # for OpenAI
logging.getLogger("httpx").setLevel(logging.ERROR)      # if using httpx
logging.getLogger("urllib3").setLevel(logging.ERROR)    # if using requests

class ChatbotCLI:
    def __init__(self, config_path="config/config.yaml"):
        """Initialize the chatbot with configuration"""
        print("🔧 Loading configuration...")
        self.config = ConfigParser(config_path)
        
        print("🤖 Initializing chatbot...")
        self.chatbot = RAGPipeline(self.config)
        self.indexer = DocumentIndexer(self.config)
        
        self.history = []
        print("✅ Chatbot ready!\n")
    
    def print_banner(self):
        """Display welcome banner"""
        print("=" * 60)
        print("         FABRIQ CHATBOT - CLI Interface")
        print("=" * 60)
        print("\nCommands:")
        print("  /help     - Show this help message")
        print("  /clear    - Clear conversation history")
        print("  /history  - Show conversation history")
        print("  /upload   - Upload documents from a directory")
        print("  /exit     - Exit the chatbot")
        print("  /quit     - Exit the chatbot")
        print("\nType your message and press Enter to chat.\n")
        print("=" * 60)
        print()
    
    def stream_response(self, prompt):
        """Display response with typewriter effect"""

        def loading_cursor(stop_event):
            cursor = "|/-\\"
            idx = 0
            while not stop_event.is_set():
                print(f"\r🤖 Assistant: Thinking... {cursor[idx % len(cursor)]}", end="", flush=True)
                idx += 1
                time.sleep(0.1)
            print("\r" + " " * 40 + "\r", end="", flush=True)  # Clear line

        stop_event = threading.Event()
        loader_thread = threading.Thread(target=loading_cursor, args=(stop_event,))
        loader_thread.start()

        try:
            response = self.chatbot.get_response(prompt, stream=True)
            stop_event.set()
            loader_thread.join()

            print("\n🤖 Assistant: ", end="", flush=True)

            full_response = []
            for chunk in response["text"]:
                text = chunk.content
                full_response.append(text)
                for ch in text:
                    print(ch, end="", flush=True)
                    time.sleep(0.01)

            print("\n")
            return "".join(full_response)

        except Exception as e:
            stop_event.set()
            loader_thread.join()
            print(f"\n❌ Error: {e}\n")
            return ""
    
    def get_file_paths(self, dir_path):
        """Get list of file paths from a directory"""
        p = Path(dir_path)
        if not p.is_dir():
            raise ValueError(f"Provided path is not a directory: {dir_path}")
        return [str(f) for f in p.glob("**/*") if f.is_file()]
    
    def upload_documents(self, dir_path):
        """Upload documents from a directory to the vector store"""
        file_paths = self.get_file_paths(dir_path)
        if not file_paths:
            print(f"No files found in directory: {dir_path}")
            return
        
        print(f"📂 Uploading {len(file_paths)} documents from {dir_path}...")
        self.indexer.index_documents(file_paths)
        print("✅ Documents uploaded and indexed successfully!\n")
    
    def show_history(self):
        """Display conversation history"""
        if not self.history:
            print("\n📜 No conversation history yet.\n")
            return
        
        print("\n📜 Conversation History:")
        print("-" * 60)
        for i, msg in enumerate(self.history, 1):
            role = "👤 You" if msg["role"] == "user" else "🤖 Assistant"
            print(f"\n{role}:")
            print(f"{msg['content']}")
            if i < len(self.history):
                print("-" * 60)
        print()
    
    def clear_history(self):
        """Clear conversation history"""
        self.history.clear()
        print("\n🗑️  Conversation history cleared.\n")
    
    def handle_command(self, user_input):
        """Handle special commands"""
        cmd = user_input.lower().strip()
        
        if cmd in ["/exit", "/quit"]:
            print("\n👋 Goodbye!\n")
            return False
        elif cmd == "/help":
            self.print_banner()
        elif cmd == "/clear":
            self.clear_history()
        elif cmd == "/history":
            self.show_history()
        elif cmd == "/upload":
            dir_path = input("📁 Enter directory path to upload documents: ").strip()
            try:
                self.upload_documents(dir_path)
            except Exception as e:
                print(f"\n❌ Error uploading documents: {e}\n")
        else:
            print(f"\n❌ Unknown command: {user_input}")
            print("Type /help to see available commands.\n")
        
        return True
    
    def run(self):
        """Main chat loop"""
        self.print_banner()
        
        try:
            while True:
                # Get user input
                try:
                    user_input = input("👤 You: ").strip()
                except EOFError:
                    print("\n👋 Goodbye!\n")
                    break
                
                # Skip empty inputs
                if not user_input:
                    continue
                
                # Handle commands
                if user_input.startswith("/"):
                    if not self.handle_command(user_input):
                        break
                    continue
                
                # Add user message to history
                self.history.append({"role": "user", "content": user_input})
                
                try:
                    # Get and stream response
                    response = self.stream_response(user_input)
                    
                    # Add assistant response to history
                    self.history.append({"role": "assistant", "content": response})
                    
                except KeyboardInterrupt:
                    print("\n\n⚠️  Response interrupted.\n")
                    continue
                except Exception as e:
                    print(f"\n❌ Error getting response: {e}\n")
                    continue
        
        except KeyboardInterrupt:
            print("\n\n👋 Goodbye!\n")
        except Exception as e:
            print(f"\n❌ Fatal error: {e}\n")
            sys.exit(1)


def main():
    """Entry point for the CLI tool"""
    parser = argparse.ArgumentParser(
        description="Chat with your Documents using Fabriq Chat CLI.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    
    parser.add_argument(
        "--config",
        "-c",
        default="config/config.yaml",
        help="Path to configuration file (default: config/config.yaml)"
    )
    
    args = parser.parse_args()
    
    # Check if config file exists
    if not Path(args.config).exists():
        print(f"❌ Config file not found: {args.config}")
        sys.exit(1)
    
    # Initialize and run chatbot
    cli = ChatbotCLI(config_path=args.config)
    cli.run()


if __name__ == "__main__":
    main()