#!/usr/bin/env python3
import code
import readline
import rlcompleter  # noqa: F401
import sys
import os
import atexit
from typing import Dict, Any
from .df_lib import *  # noqa: F401, F403, E402
from .algebra_lib import *  # noqa: F401, F403, E402
from .str_lib import *  # noqa: F401, F403, E402
from .docs_lib import *  # noqa: F401, F403, E402

def interactive_shell(local_vars: Dict[str, Any]) -> None:
    """
    Launch an interactive prompt for inspecting and modifying local variables,
    with blue-colored output and a prompt in white. An extra blank line is inserted
    before each new input prompt.
    
    local_vars: dictionary of local variables to be available in the interactive shell.
    """
    
    # ANSI color escape codes.
    BLUE = "\033[94m"
    WHITE = "\033[37m"
    RESET = "\033[0m"
    
    # Function to set up readline history.
    def setup_readline() -> None:
        HISTORY_FILE = os.path.expanduser("~/.rgwfuncs_shell_history")
        readline.set_history_length(1000)
        readline.parse_and_bind("tab: complete")
        if os.path.exists(HISTORY_FILE):
            try:
                readline.read_history_file(HISTORY_FILE)
            except Exception as e:
                print(f"Warning: Could not load history file: {e}")
        atexit.register(readline.write_history_file, HISTORY_FILE)
    
    # BlueStdout: wrap stdout so output is printed in blue.
    class BlueStdout:
        def __init__(self, wrapped):
            self.wrapped = wrapped
            self.at_line_start = True
            
        def write(self, s):
            # If s matches our prompt strings, write verbatim.
            if s == sys.ps1 or s == sys.ps2:
                self.wrapped.write(s)
                return
            # Write each new line in blue.
            lines = s.split('\n')
            for i, line in enumerate(lines):
                if self.at_line_start and line:
                    self.wrapped.write(BLUE + line)
                else:
                    self.wrapped.write(line)
                if i < len(lines) - 1:
                    self.wrapped.write('\n' + RESET)
                    self.at_line_start = True
                else:
                    self.at_line_start = (line == "")
                    
        def flush(self):
            self.wrapped.flush()
            
        def isatty(self):
            return self.wrapped.isatty()
        
        def fileno(self):
            return self.wrapped.fileno()
        
        def __getattr__(self, attr):
            return getattr(self.wrapped, attr)
    
    # ColorInteractiveConsole: subclass InteractiveConsole to restore the original
    # stdout during input, and print an extra blank line before each prompt.
    class ColorInteractiveConsole(code.InteractiveConsole):
        def raw_input(self, prompt=""):
            saved_stdout = sys.stdout
            sys.stdout = sys.__stdout__
            try:
                # Print an extra newline before the prompt.
                print("")
                line = input(prompt)
            except EOFError:
                raise
            finally:
                sys.stdout = saved_stdout
            return line
    
    # Validate that local_vars is a dictionary.
    if not isinstance(local_vars, dict):
        raise TypeError("local_vars must be a dictionary")
    
    setup_readline()
    
    # Merge globals into local_vars.
    local_vars.update(globals())
    
    # Wrap ANSI color codes with markers for zero-width in the prompt.
    sys.ps1 = "\001" + WHITE + "\002" + ">>> " + "\001" + RESET + "\002"
    sys.ps2 = "\001" + WHITE + "\002" + "... " + "\001" + RESET + "\002"
    
    # Use BlueStdout to wrap the original stdout.
    sys.stdout = BlueStdout(sys.__stdout__)
    
    # Create the custom interactive console.
    console = ColorInteractiveConsole(locals=local_vars)
    
    banner = ("Welcome to the rgwfuncs interactive shell.\n"
              "Use up/down arrows for command history.\n"
              "Type 'exit()' or Ctrl+D to quit.")
    exitmsg = "Goodbye."
    
    try:
        console.interact(banner=banner)
    finally:
        print(exitmsg)

