"""
Vault-backed auth provider for Wirlwind telemetry.

Bridges the CredentialResolver to Wirlwind's auth interface abstraction,
allowing telemetry connections to auto-resolve credentials from the vault.

The NtermAuthProvider is created by nterm_desktop.py and passed to each
TelemetryWidget. Wirlwind has zero imports from nterm — it only sees the
auth interface contract.

Usage:
    from nterm.vault_auth_provider import NtermAuthProvider

    provider = NtermAuthProvider(resolver)
    widget = TelemetryWidget(auth_provider=provider)
"""

from __future__ import annotations
import logging
from typing import Optional

logger = logging.getLogger(__name__)


class NtermAuthProvider:
    """
    Auth provider for Wirlwind telemetry backed by nterm's credential vault.

    Implements the same interface as SimpleAuthProvider so Wirlwind can
    use either without code changes. The boundary is the auth interface —
    Wirlwind never imports from nterm.vault directly.
    """

    def __init__(self, resolver):
        """
        Args:
            resolver: CredentialResolver instance from the desktop wrapper.
                      Shared across all telemetry tabs — vault unlock state
                      is global.
        """
        self._resolver = resolver

    @property
    def is_available(self) -> bool:
        """Check if vault is unlocked and credentials are resolvable."""
        try:
            return (
                    self._resolver is not None
                    and self._resolver.is_initialized()
                    and self._resolver.store.is_unlocked
            )
        except Exception:
            return False

    def get_credentials(
            self,
            hostname: str,
            port: int = 22,
            username: Optional[str] = None,
    ) -> Optional[dict]:
        """
        Resolve credentials for a device.

        Returns a dict matching Wirlwind's expected auth format:
            {
                "username": str,
                "password": str | None,
                "key_data": str | None,       # PEM key content
                "key_passphrase": str | None,
                "auth_method": str,           # "password" | "key"
            }

        Returns None if no credential matches or vault is locked.
        """
        if not self.is_available:
            logger.debug(f"Vault not available for {hostname}")
            return None

        try:
            profile = self._resolver.resolve_or_default(
                hostname, port=port
            )

            if profile is None:
                logger.debug(f"No credential matched {hostname}")
                return None

            if not profile.auth_methods:
                logger.warning(f"Credential for {hostname} has no auth methods")
                return None

            # Use the first (highest priority) auth method
            auth = profile.auth_methods[0]

            result = {
                "username": username or auth.username,
                "password": None,
                "key_data": None,
                "key_passphrase": None,
                "auth_method": "password",
            }

            if auth.method.name == "KEY_STORED":
                result["key_data"] = auth.key_data
                result["key_passphrase"] = auth.key_passphrase
                result["auth_method"] = "key"
            elif auth.method.name == "KEY_FILE":
                # Read key file and provide as data
                try:
                    with open(auth.key_path, "r") as f:
                        result["key_data"] = f.read()
                    result["key_passphrase"] = auth.key_passphrase
                    result["auth_method"] = "key"
                except (OSError, IOError) as e:
                    logger.error(f"Failed to read key file {auth.key_path}: {e}")
                    # Fall through to password if available
                    if auth.password:
                        result["password"] = auth.password
                    else:
                        return None
            elif auth.method.name == "PASSWORD":
                result["password"] = auth.password
            elif auth.method.name == "AGENT":
                result["auth_method"] = "agent"

            logger.info(
                f"Resolved credential for {hostname}: "
                f"user={result['username']}, method={result['auth_method']}"
            )
            return result

        except Exception as e:
            logger.error(f"Credential resolution failed for {hostname}: {e}")
            return None

    def get_jump_host(self, hostname: str, port: int = 22) -> Optional[dict]:
        """
        Resolve jump host config for a device, if any.

        Returns:
            {
                "hostname": str,
                "port": int,
                "username": str,
                "auth_method": str,
                "password": str | None,
                "key_data": str | None,
                "requires_touch": bool,
                "touch_prompt": str | None,
            }

        Returns None if no jump host configured for this device.
        """
        if not self.is_available:
            return None

        try:
            profile = self._resolver.resolve_or_default(
                hostname, port=port
            )

            if profile is None or not profile.has_jump_host:
                return None

            jh = profile.jump_hosts[0]
            result = {
                "hostname": jh.hostname,
                "port": jh.port,
                "username": None,
                "auth_method": "agent",
                "password": None,
                "key_data": None,
                "requires_touch": jh.requires_touch,
                "touch_prompt": jh.touch_prompt,
            }

            if jh.auth:
                result["username"] = jh.auth.username
                if jh.auth.method.name == "PASSWORD":
                    result["auth_method"] = "password"
                    result["password"] = jh.auth.password
                elif jh.auth.method.name in ("KEY_STORED", "KEY_FILE"):
                    result["auth_method"] = "key"
                    result["key_data"] = jh.auth.key_data

            return result

        except Exception as e:
            logger.error(f"Jump host resolution failed for {hostname}: {e}")
            return None