"""
Authentication commands for HLA-Compass CLI.
"""

import os
import click
from rich.prompt import Prompt
from typing import Optional

from ..auth import Auth
from ..config import Config
from .utils import console, verbose_option, _ensure_verbose

@click.group()
def auth():
    """Authentication and credential management
    
    Manage your HLA-Compass platform credentials for publishing modules.
    """
    pass

@auth.command("login")
@click.option("--env", 
              type=click.Choice(["dev", "staging", "prod"]), 
              default="dev",
              help="Target environment")
@click.option("--email", 
              required=False,
              help="Your email address (for non-browser login)")
@click.option("--password", 
              required=False,
              help="Your password (for non-browser login)")
@click.option("--browser/--no-browser", 
              default=True, 
              help="Use browser-based SSO login (default)")
@click.option("--interactive", 
              is_flag=True, 
              help="Force interactive prompt login (disable browser)")
def auth_login(env: str, email: Optional[str], password: Optional[str], browser: bool, interactive: bool):
    """Login to HLA-Compass platform
    
    Authenticate with the platform and store credentials securely.
    Defaults to opening a browser for Single Sign-On (SSO).
    
    Use --interactive or provide --email/--password to skip the browser.
    
    Example:
        hla-compass auth login                # Browser SSO
        hla-compass auth login --interactive  # Prompt for email/password
    """
    Config.set_environment(env)

    try:
        auth_client = Auth()

        # 1. Explicit credentials provided via flags
        if email and password:
            auth_client.login(email=email, password=password, environment=env)
        
        # 2. Interactive prompt requested (or browser disabled explicitely)
        elif interactive or not browser:
            if not email:
                email = Prompt.ask("Email")
            if not password:
                password = Prompt.ask("Password", password=True)
            auth_client.login(email=email, password=password, environment=env)

        # 3. Default: Browser SSO
        else:
            console.print(f"[bold cyan]Opening browser for SSO login to {env}...[/bold cyan]")
            try:
                auth_client.login_browser(environment=env)
            except Exception as e:
                console.print(f"[yellow]Browser login failed: {e}[/yellow]")
                console.print("Falling back to interactive login.")
                if not email:
                    email = Prompt.ask("Email")
                if not password:
                    password = Prompt.ask("Password", password=True)
                auth_client.login(email=email, password=password, environment=env)

        console.print(f"[green]✓[/green] Successfully logged in to {env} environment")
        console.print(f"[dim]Credentials stored in: {Config.get_credentials_path()}[/dim]")

        try:
            from ..client import APIClient
            client = APIClient()
            user_payload = client.get_current_user()
            user_info = user_payload.get("user") or user_payload
            profile = _build_profile_from_user(user_info, env)
            Config.update_profile(env, profile, set_active=True)
            _update_author_metadata_from_user(user_info)

            active_org = profile.get("activeOrgId")
            if active_org:
                org_label = active_org
                for org in profile.get("organizations") or []:
                    if str(org.get("id")) == str(active_org):
                        if org.get("name"):
                            org_label = f"{org['name']} ({active_org})"
                        break
                console.print(f"[dim]Active organization:[/dim] {org_label}")
        except Exception as exc:
            if Config.get_environment() == 'dev':
                 # Suppress specific dev errors or warn
                 pass
            console.print(f"[yellow]⚠[/yellow] Logged in but profile sync failed: {exc}")

    except Exception as e:
        console.print(f"[red]✗ Login failed:[/red] {e}")
        raise click.Abort()

@auth.command("logout")
def auth_logout():
    """Logout and clear stored credentials"""
    try:
        auth_client = Auth()
        auth_client.logout()
        console.print("[green]✓[/green] Successfully logged out")
        console.print("[dim]All credentials have been cleared[/dim]")
    except Exception as e:
        console.print(f"[yellow]Warning:[/yellow] {e}")

@auth.command("status")
def auth_status():
    """Show current authentication status"""
    from rich.table import Table
    try:
        auth_client = Auth()
        is_authed = auth_client.is_authenticated()
        
        table = Table(title="Authentication Status")
        table.add_column("Property", style="cyan")
        table.add_column("Value", style="green" if is_authed else "red")
        
        table.add_row("Authenticated", "Yes" if is_authed else "No")
        table.add_row("Environment", Config.get_environment())
        table.add_row("API Endpoint", Config.get_api_endpoint())
        table.add_row("Credentials Path", str(Config.get_credentials_path()))
        
        if is_authed:
            table.add_row("Token Status", "Valid")
        
        console.print(table)
        
    except Exception as e:
        console.print(f"[red]Error:[/red] {e}")
        raise click.Abort()

@auth.command("use-org")
@click.argument("org_id")
@click.option(
    "--env",
    type=click.Choice(["dev", "staging", "prod"]),
    help="Override environment profile (defaults to current environment)",
)
def auth_use_org(org_id: str, env: Optional[str]):
    """Select a default organization for CLI operations."""
    target_env = env or Config.get_environment()
    Config.set_environment(target_env)

    profile = Config.get_profile(target_env)
    if not profile:
        console.print(
            "[red]No profile metadata found. Run 'hla-compass auth login' first.[/red]"
        )
        raise click.Abort()

    organizations = profile.get("organizations") or []
    if not organizations:
        console.print(
            "[red]No organizations recorded for this profile. Login and try again.[/red]"
        )
        raise click.Abort()

    normalized = org_id.strip().lower()
    match = None
    for org in organizations:
        candidates = {
            str(org.get("id") or "").lower(),
            str(org.get("external_id") or "").lower(),
            str(org.get("name") or "").lower(),
        }
        if normalized and normalized in candidates:
            match = org
            break

    if not match:
        console.print("[red]Organization not found in profile.[/red]")
        console.print("Known organizations:")
        for org in organizations:
            console.print(
                f"  • {org.get('name') or org.get('id')} (id={org.get('id')}, external_id={org.get('external_id')})"
            )
        raise click.Abort()

    selected_id = match.get("id") or org_id
    Config.set_active_org(selected_id, target_env)
    console.print(
        f"[green]✓[/green] Active organization set to {match.get('name') or selected_id} for {target_env}"
    )

# Helpers reused from original CLI
def _build_profile_from_user(user: dict, env: str) -> dict:
    organizations = user.get("organizations") or []
    primary_org = user.get("organization_id") or user.get("organizationId")
    if not primary_org and isinstance(organizations, list):
        primary = next((org for org in organizations if org.get("is_primary")), None)
        if primary:
            primary_org = primary.get("id")
        elif organizations:
            primary_org = organizations[0].get("id")

    return {
        "environment": env,
        "userId": user.get("id"),
        "email": user.get("email"),
        "name": user.get("name"),
        "organizations": organizations,
        "activeOrgId": primary_org,
        "primaryOrgId": primary_org,
        "platformRole": user.get("platform_role") or user.get("platformRole"),
    }

def _update_author_metadata_from_user(user: dict) -> None:
    config_data = Config.load_config_data()
    author = config_data.get("author") or {}
    changed = False
    if user.get("name"):
        author["name"] = user["name"]
        changed = True
    if user.get("email"):
        author["email"] = user["email"]
        changed = True
    if user.get("organization") and isinstance(user["organization"], dict):
        org_name = user["organization"].get("name")
        if org_name:
            author["organization"] = org_name
            changed = True

    if changed:
        config_data["author"] = author
        Config.save_config_data(config_data)
