from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
from rich.live import Live
from rich import box
import questionary
from questionary import Separator
from nova_cli.nova_core.ai.utils import MODELS  # CLI model selector list

class Interface:
    def __init__(self):
        # force_terminal=True and width=100 ensures it doesn't collapse into a vertical line
        self.console = Console(width=120, force_terminal=True)

    def print(self, *args, **kwargs):
        # We set soft_wrap=True as default unless specifically told otherwise
        if "soft_wrap" not in kwargs:
            kwargs["soft_wrap"] = True
        self.console.print(*args, **kwargs)

    def input(self, prompt_text):
        """Renders prompt with Rich and 'locks' it for readline to prevent backspacing."""
        import sys
        import re
        
        # 1. Capture the formatted ANSI prompt from Rich
        with self.console.capture() as capture:
            self.console.print(prompt_text, end="")
        raw_prompt = capture.get()
        
        # 2. Wrap ANSI codes in special markers (\001 and \002) for Readline.
        # This tells the terminal: 'These characters have 0 width, do not backspace over them.'
        if sys.platform != "win32":
            # Enclose escape sequences in \x01 and \x02
            # Uses octal escapes \001 and \002 which are compatible with re.sub replacement strings
            processed_prompt = re.split(r'(\x1b\[[0-9;]*[mK])', raw_prompt)
            processed_prompt = "".join([f"\001{part}\002" if part.startswith('\x1b') else part for part in processed_prompt])
        else:
            processed_prompt = raw_prompt
            
        return input(processed_prompt)
    
    def script_output(self, text: str, title: str = "Script Output"):
        """Displays script output using raw literal Text to prevent 'Double Formatting'."""
        if not text.strip():
            return
        
        # We wrap the text in a 'Text' object with markup=False 
        # to ensure Rich treats it as a literal string (no backspacing/swallowing tags)
        from rich.text import Text
        content = Text(text.strip()) 
        
        self.console.print(Panel(
            content,
            title=f"[dim]{title}[/dim]",
            border_style="dim",
            padding=(0, 1),
            expand=True  # Expand ensures the box stays consistent regardless of line length
        ))

    def create_loader(self, text=""):
        return self.console.status(f"[bold cyan]{text}[/bold cyan]", spinner="dots12", spinner_style="cyan")

    def show_model_selector(self, current_model: str):
        # Build (provider, model) pairs so we can return both
        options = []
        for provider, models in MODELS.items():
            for m in models:
                options.append((provider, m))

        # Show only model names in UI, but keep provider in the value
        choices = [
            questionary.Choice(title=model, value=(provider, model))
            for provider, model in options
        ]

        # Default selection
        default_value = None
        for provider, model in options:
            if model == current_model:
                default_value = (provider, model)
                break

        answer = questionary.select(
            "Model:",
            choices=choices,
            default=default_value,
            style=questionary.Style([
                ("qmark", "fg:#00ffff bold"),
                ("question", "fg:#ffffff bold"),
                ("answer", "fg:#00ffff bold"),
                ("pointer", "fg:#00ffff bold"),
                ("selected", "fg:#00ffff"),
            ]),
        ).ask()

        if not answer:
            # keep current model, assume groq if unknown
            return current_model, "groq"

        provider, model = answer
        return model, provider



    def show_git_options(self, auto_commit, auto_push):
        """
        Displays the Git Configuration Menu with improved UX.
        """
        # Define visual states
        # Green circle for ON, Dim/Red for OFF
        state_ac = "🟢 ON " if auto_commit else "🔴 OFF"
        state_ap = "🟢 ON " if auto_push else "🔴 OFF"

        choices = [
            Separator("--- AUTOMATION SETTINGS ---"),
            f"Toggle Auto-Commit  [{state_ac}]",
            f"Toggle Auto-Push    [{state_ap}]",
            
            Separator("--- ACTIONS ---"),
            "📝 Manual Commit (Stage & Commit all)",
            "🚀 Push to Origin",
            "⬇️  Pull from Origin",
            "📊 Git Status",
            
            Separator("--- EXIT ---"),
            "🔙 Back to Terminal"
        ]

        answer = questionary.select(
            "Git Operations Center",
            choices=choices,
            style=questionary.Style([
                ('qmark', 'fg:#00ff00 bold'),       
                ('question', 'fg:#ffffff bold'),    
                ('answer', 'fg:#00ff00 bold'),      
                ('pointer', 'fg:#00ff00 bold'),     
                ('selected', 'fg:#00ff00'),
                ('separator', 'fg:#666666'),
            ]),
            use_indicator=True
        ).ask()
        
        # Clean up the string to match logic (remove emojis/brackets for the logic check)
        if not answer: return "Back"
        if "Back" in answer: return "Back"
        if "Auto-Commit" in answer: return "Toggle Auto-Commit"
        if "Auto-Push" in answer: return "Toggle Auto-Push"
        if "Manual Commit" in answer: return "Manual Commit"
        if "Push" in answer: return "Push"
        if "Pull" in answer: return "Pull"
        if "Git Status" in answer: return "Git Status"
        
        return answer

    def get_multiline_input(self):
        self.print("[dim]Paste code below. Type 'EOF' to finish.[/dim]")
        lines = []
        while True:
            try:
                line = self.console.input()
                if line.strip().upper() == "EOF": break
                lines.append(line)
            except KeyboardInterrupt:
                return ""
        return "\n\n".join(lines)

    def clear(self):
        self.console.clear()

    def display_header(self, model_name, cwd):
        self.clear()
        self.print("[dim][/dim]")
        self.print("[dim]──────────────────────────────────────[/dim]")
        self.print(f"[bold white]NOVA[/bold white] [dim]│[/dim] [cyan]{model_name}[/cyan]")
        self.print(f"[dim]{cwd}[/dim]")
        self.print("[dim]──────────────────────────────────────[/dim]")

    def stream_response(self, chat_generator):
        full_text = ""
        self.print() 
        
        with Live(Markdown(""), refresh_per_second=15, auto_refresh=True) as live:
            chunk_counter = 0
            for chunk in chat_generator:
                if chunk.text:
                    full_text += chunk.text
                    chunk_counter += 1
                    if chunk_counter % 4 == 0:
                        live.update(Markdown(full_text))
            live.update(Markdown(full_text))
        
        self.print() 
        return full_text

ui = Interface()