"""
Authentication module using the existing MCP device flow.

Reuses the existing endpoints:
- POST /public/mcp-device/start -> get user_code + session_id
- POST /public/mcp-device/exchange -> exchange for API key
"""
import os
import time
import webbrowser
import httpx
from rich.console import Console
from rich.panel import Panel

from config import (
    NIA_SYNC_DIR,
    CONFIG_FILE,
    load_config,
    save_config,
    clear_config,
    get_api_base_url,
)

console = Console()

# Polling configuration
POLL_INTERVAL_SECONDS = 2
MAX_POLL_ATTEMPTS = 150  # 5 minutes max


def is_authenticated() -> bool:
    """Check if user is authenticated (has API key stored)."""
    config = load_config()
    return bool(config.get("api_key"))


def get_api_key() -> str | None:
    """Get the stored API key."""
    config = load_config()
    return config.get("api_key")


def login() -> bool:
    """
    Authenticate using the MCP device flow.

    1. Call /public/mcp-device/start to get user_code
    2. Open browser for user to authenticate
    3. Poll /public/mcp-device/exchange until ready
    4. Store API key locally
    """
    try:
        # Step 1: Start device session
        console.print("Starting authentication...")

        with httpx.Client(timeout=30) as client:
            response = client.post(f"{get_api_base_url()}/public/mcp-device/start")
            response.raise_for_status()

            data = response.json()
            user_code = data["user_code"]
            authorization_session_id = data["authorization_session_id"]
            verification_url = data["verification_url"]

        # Step 2: Show code and open browser
        console.print()
        console.print(Panel.fit(
            f"[bold cyan]Your code: {user_code}[/bold cyan]\n\n"
            "1. A browser window will open\n"
            "2. Sign in to your Nia account\n"
            "3. The code will be pre-filled\n"
            "4. Complete the setup, then return here",
            title="Authentication Code",
        ))
        console.print()

        # Open browser
        webbrowser.open(verification_url)
        console.print(f"[dim]Browser opened to: {verification_url}[/dim]")
        console.print()
        console.print("Waiting for authentication...")

        # Step 3: Poll for completion
        api_key = _poll_for_api_key(authorization_session_id, user_code)

        if not api_key:
            return False

        # Step 4: Store credentials
        save_config({
            "api_key": api_key,
        })

        return True

    except httpx.HTTPStatusError as e:
        console.print(f"[red]HTTP error: {e.response.status_code}[/red]")
        return False
    except Exception as e:
        console.print(f"[red]Error during login: {e}[/red]")
        return False


def _poll_for_api_key(session_id: str, user_code: str) -> str | None:
    """Poll the exchange endpoint until authentication completes."""
    with httpx.Client(timeout=30) as client:
        with console.status("[dim]Waiting for browser authentication...[/dim]") as status:
            for attempt in range(MAX_POLL_ATTEMPTS):
                try:
                    response = client.post(
                        f"{get_api_base_url()}/public/mcp-device/exchange",
                        json={
                            "authorization_session_id": session_id,
                            "user_code": user_code,
                        }
                    )

                    if response.status_code == 200:
                        data = response.json()
                        status.stop()
                        console.print("[green]Authentication successful![/green]")
                        return data.get("api_key")

                    elif response.status_code == 400:
                        # Not ready yet - still pending or authorized but not ready
                        detail = response.json().get("detail", "")
                        if "not yet authorized" in detail.lower() or "complete the setup" in detail.lower():
                            # Still waiting for user to complete in browser
                            time.sleep(POLL_INTERVAL_SECONDS)
                            continue
                        else:
                            status.stop()
                            console.print(f"[red]Error: {detail}[/red]")
                            return None

                    elif response.status_code == 410:
                        status.stop()
                        console.print("[red]Session expired. Please try again.[/red]")
                        return None

                    elif response.status_code == 409:
                        status.stop()
                        console.print("[red]Session already used. Please try again.[/red]")
                        return None

                    elif response.status_code == 404:
                        status.stop()
                        console.print("[red]Invalid session. Please try again.[/red]")
                        return None

                    else:
                        status.stop()
                        console.print(f"[red]Unexpected error: {response.status_code}[/red]")
                        return None

                except httpx.RequestError as e:
                    console.print(f"[yellow]Network error, retrying... ({e})[/yellow]")
                    time.sleep(POLL_INTERVAL_SECONDS)
                    continue

    console.print("[red]Timeout waiting for authentication. Please try again.[/red]")
    return None


def logout():
    """Clear stored credentials."""
    clear_config()
    console.print("[green]Credentials cleared.[/green]")
