import click
import httpx
import json
import os
from prompt_toolkit import Application
from prompt_toolkit.layout import Layout, HSplit, Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.styles import Style
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from rich.theme import Theme
from .config import save_api_key, save_project_config
from .client import CortifClient

console = Console(theme=Theme({
    "info": "cyan",
    "warning": "yellow",
    "error": "red",
    "success": "green",
}))

def read_project_config():
    try:
        with open('cortif.json', 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return None
    except json.JSONDecodeError:
        return None

@click.group()
def cli():
    pass

@cli.command()
def login():
    console.print(Panel("Welcome to Cortif!", style="bold cyan"))
    host = click.prompt("Enter your Cortif app URL", default="https://app.cortif.ai")
    api_key = click.prompt("Enter your API key (ctf_...)", hide_input=True)
    
    if not api_key.startswith("ctf_"):
        console.print("[error]Invalid API key format. It should start with 'ctf_'.[/error]")
        return
        
    host = host.rstrip('/')
    try:
        response = httpx.get(
            f"{host}/api/user/api-keys",
            headers={"Authorization": f"Bearer {api_key}"}
        )
        response.raise_for_status()
    except httpx.HTTPStatusError as e:
        if e.response.status_code == 401:
            console.print("[error]Login failed: Invalid API key.[/error]")
        else:
            console.print(f"[error]Login failed: Server returned status {e.response.status_code}[/error]")
        return
    except httpx.RequestError as e:
        console.print(f"[error]Login failed: Could not connect to {host}. Error: {e}[/error]")
        return

    save_api_key(api_key, host)
    console.print(Panel(
        f"[success]✓ Successfully logged in to {host}![/success]",
        border_style="green",
        title="Login Successful"
    ))

class ProjectSelector:
    def __init__(self, projects):
        self.projects = projects
        self.selected_index = 0
        self.kb = KeyBindings()
        self.style = Style.from_dict({
            'selected': 'reverse #00ff00',
            'header': 'bold #00ffff',
            'instruction': 'italic #888888',
        })
        
        @self.kb.add('up')
        def up(event):
            self.selected_index = max(0, self.selected_index - 1)
            self._update_display()

        @self.kb.add('down')
        def down(event):
            self.selected_index = min(len(self.projects) - 1, self.selected_index + 1)
            self._update_display()

        @self.kb.add('enter')
        def enter(event):
            event.app.exit()

        @self.kb.add('q')
        def quit(event):
            event.app.exit()
            self.selected_index = -1

        console.print(Panel("[bold cyan]Cortif Projects[/bold cyan]", expand=False))

        self.text_area = FormattedTextControl(self._get_formatted_text)
        root_container = HSplit([
            Window(height=1, content=FormattedTextControl([
                ('class:instruction', '↑↓ Navigate • Enter Select • q Quit')
            ])),
            Window(content=self.text_area)
        ])

        self.layout = Layout(root_container)
        self.app = Application(
            layout=self.layout,
            key_bindings=self.kb,
            full_screen=True,
            style=self.style
        )

    def _get_formatted_text(self):
        lines = []
        for i, proj in enumerate(self.projects):
            if i == self.selected_index:
                lines.append(("class:selected", f"→ {proj['name']} (ID: {proj['id']})\n"))
            else:
                lines.append(("", f"  {proj['name']} (ID: {proj['id']})\n"))
        return lines

    def _update_display(self):
        self.text_area.text = self._get_formatted_text()

    def run(self):
        self.app.run()
        if self.selected_index >= 0:
            return self.projects[self.selected_index]
        return None

@cli.command()
def current():
    """Show information about the currently linked project."""
    config = read_project_config()
    if not config:
        console.print("[error]No project linked to this directory.[/error]")
        console.print("Run [bold]cortif init[/bold] to link a project.", style="info")
        return

    try:
        client = CortifClient()
    except ConnectionError as e:
        console.print(f"[error]{str(e)}[/error]")
        return

    result = client.get_projects()
    if not result or not result.get("success"):
        console.print("[error]Failed to fetch project information.[/error]")
        return

    projects = result["data"]["data"]
    current_project = next((p for p in projects if p["id"] == config["project_id"]), None)
    
    if not current_project:
        console.print("[error]Project not found. It may have been deleted.[/error]")
        return

    table = Table(show_header=False, box=None, padding=(0, 1))
    table.add_row("Project Name:", f"[cyan bold]{current_project['name']}[/cyan bold]")
    table.add_row("Project ID:", f"[blue]{current_project['id']}[/blue]")
    table.add_row("Organization ID:", f"[blue]{config['organization_id']}[/blue]")
    table.add_row("Run ID Template:", f"[green]{config['run_id_template']}[/green]")
    
    console.print(Panel(table, title="Current Project", border_style="cyan"))

@cli.command()
def projects():
    """List projects in your organization with interactive selection."""
    try:
        client = CortifClient()
    except ConnectionError as e:
        console.print(f"[error]{str(e)}[/error]")
        return
        
    result = client.get_projects()
    if result and result.get("success"):
        projects = result["data"]["data"]
        if not projects:
            console.print("[warning]No projects found.[/warning]")
            return
            
        selector = ProjectSelector(projects)
        selected_project = selector.run()
        
        if selected_project:
            table = Table(show_header=False, box=None, padding=(0, 1))
            table.add_row("Name:", f"[cyan bold]{selected_project['name']}[/cyan bold]")
            table.add_row("ID:", f"[blue]{selected_project['id']}[/blue]")
            console.print(Panel(
                table,
                title="Selected Project",
                border_style="cyan"
            ))
    else:
        console.print("[error]Failed to fetch projects.[/error]")

@cli.command()
def rm():
    """Remove project configuration from current directory."""
    if not os.path.exists('cortif.json'):
        console.print("[warning]No project configuration found in this directory.[/warning]")
        return
    
    try:
        with open('cortif.json', 'r') as f:
            config = json.load(f)
            project_id = config.get('project_id')
            
            # Try to get project name if possible
            try:
                client = CortifClient()
                result = client.get_projects()
                if result and result.get("success"):
                    projects = result["data"]["data"]
                    project = next((p for p in projects if p["id"] == project_id), None)
                    if project:
                        project_name = project["name"]
                    else:
                        project_name = project_id
                else:
                    project_name = project_id
            except:
                project_name = project_id
    except:
        project_name = "Unknown"
    
    try:
        os.remove('cortif.json')
        console.print(Panel(
            "\n".join([
                "[success]✓ Successfully removed project configuration[/success]",
                f"[cyan]Unlinked: {project_name}[/cyan]",
            ]),
            title="Project Removed",
            border_style="yellow"
        ))
    except Exception as e:
        console.print(f"[error]Failed to remove project configuration: {str(e)}[/error]")

@cli.command()
def init():
    """Initialize a local project and link it to Cortif."""
    try:
        client = CortifClient()
    except ConnectionError as e:
        console.print(f"[error]{str(e)}[/error]")
        return

    result = client.get_projects()
    if not result or not result.get("success"):
        console.print("[error]Failed to fetch projects. Cannot initialize.[/error]")
        return
        
    projects = result["data"]["data"]
    if not projects:
        console.print("[warning]No projects found in your organization.[/warning]")
        console.print("Please create one in the web app first.", style="info")
        return

    selector = ProjectSelector(projects)
    selected_project = selector.run()
    
    if not selected_project:
        console.print("[warning]No project selected.[/warning]")
        return
        
    console.clear()
    project_id = selected_project["id"]
    organization_id = selected_project.get("organization_id")
    
    # Generate a run ID template based on project name
    run_id_template = f"local_{selected_project['name'].lower().replace(' ', '_')}"
    
    save_project_config(project_id, organization_id, run_id_template)
    console.print(Panel(
        "\n".join([
            "[success]✓ Successfully linked local directory[/success]",
            f"[cyan]Project: {selected_project['name']}[/cyan]",
            "",
            "[italic]Note: A `cortif.json` file has been created.[/italic]",
            "[italic yellow]Do not commit this file if your project is public.[/italic yellow]"
        ]),
        title="Project Initialized",
        border_style="green"
    ))

if __name__ == "__main__":
    cli()
