"""
Ghostunnel SSL/TLS Tunnel Integration
======================================

Secure SSL/TLS proxy with mutual authentication for non-TLS services.
Features:
- TLS termination
- Client certificate verification
- Proxying to TCP services
"""

import logging
import subprocess
from dataclasses import dataclass
from datetime import datetime

logger = logging.getLogger(__name__)


@dataclass
class GhostunnelConfig:
    """Ghostunnel configuration."""

    listen: str
    target: str
    cacert: str | None = None
    cert: str | None = None
    key: str | None = None
    clientcert: str | None = None
    acceptonly: str | None = None
    status: str | None = "127.0.0.1:8080"


# ─── GHOSTUNNEL MANAGER ───────────────────────────────────────────


class GhostunnelManager:
    """Manages Ghostunnel processes."""

    def __init__(self, ghostunnel_bin: str = "ghostunnel"):
        self.ghostunnel_bin = ghostunnel_bin
        self._available = self._check_available()
        self.processes: dict[str, subprocess.Popen] = {}

    def _check_available(self) -> bool:
        """Check if ghostunnel is installed."""
        try:
            result = subprocess.run([self.ghostunnel_bin, "version"], capture_output=True, timeout=5)
            return result.returncode == 0
        except (subprocess.TimeoutExpired, FileNotFoundError):
            return False

    def start_tunnel(self, config: GhostunnelConfig) -> str:
        """
        Start a new tunnel.

        Args:
            config: Ghostunnel configuration

        Returns:
            Process ID of the tunnel
        """
        if not self._available:
            return "stub_tunnel"

        cmd = [
            self.ghostunnel_bin,
            "server",
            "--listen",
            config.listen,
            "--target",
            config.target,
        ]

        if config.cacert:
            cmd.extend(["--cacert", config.cacert])
        if config.cert:
            cmd.extend(["--cert", config.cert])
        if config.key:
            cmd.extend(["--key", config.key])
        if config.clientcert:
            cmd.extend(["--clientcert", config.clientcert])
        if config.acceptonly:
            cmd.extend(["--acceptonly", config.acceptonly])
        if config.status:
            cmd.extend(["--status", config.status])

        try:
            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            self.processes[config.listen] = process
            return str(process.pid)
        except Exception as e:
            logger.error(f"Failed to start ghostunnel: {e}")
            return ""

    def stop_tunnel(self, listen_addr: str) -> bool:
        """
        Stop a tunnel by listening address.

        Args:
            listen_addr: Listening address of the tunnel

        Returns:
            Success status
        """
        process = self.processes.get(listen_addr)
        if process:
            process.terminate()
            try:
                process.wait(timeout=5)
                del self.processes[listen_addr]
                return True
            except subprocess.TimeoutExpired:
                process.kill()
                del self.processes[listen_addr]
                return True
        return False

    def stop_all(self) -> int:
        """Stop all tunnels. Returns count of stopped processes."""
        count = 0
        for addr in list(self.processes.keys()):
            if self.stop_tunnel(addr):
                count += 1
        return count

    def get_status(self) -> dict[str, str]:
        """Get status of all tunnels."""
        status = {}
        for addr, process in self.processes.items():
            status[addr] = {
                "pid": process.pid,
                "alive": process.poll() is None,
                "started_at": datetime.utcnow().isoformat(),
            }
        return status


# ─── GLOBAL SINGLETON ─────────────────────────────────────────────

_manager: GhostunnelManager | None = None


def get_ghostunnel_manager() -> GhostunnelManager:
    """Get or create Ghostunnel manager."""
    global _manager
    if _manager is None:
        _manager = GhostunnelManager()
    return _manager


def start_tunnel(listen: str, target: str, **kwargs) -> str:
    """
    Convenience function to start a tunnel.

    Args:
        listen: Listen address (host:port)
        target: Target address (host:port)
        **kwargs: Extra config options
    """
    config = GhostunnelConfig(listen=listen, target=target, **kwargs)
    manager = get_ghostunnel_manager()
    return manager.start_tunnel(config)


def stop_tunnel(listen: str) -> bool:
    """Convenience function to stop a tunnel."""
    manager = get_ghostunnel_manager()
    return manager.stop_tunnel(listen)


def stop_all_tunnels() -> int:
    """Convenience function to stop all tunnels."""
    manager = get_ghostunnel_manager()
    return manager.stop_all()
