import os
import subprocess
import logging

logger = logging.getLogger(__name__)

def run_local_command(args):
    """Executes a command on the local system."""
    try:
        res = subprocess.run(args, capture_output=True, text=True, timeout=15)
        if res.returncode == 0:
            return res.stdout
        else:
            return f"Error executing command: {res.stderr}"
    except Exception as e:
        return f"Failed to run command locally: {str(e)}"

def run_ssh_command(host, username, command, password=None, key_filename=None):
    """Runs a command via SSH on a remote host (e.g., Proxmox node)."""
    try:
        import paramiko
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        # Connect using password or key
        ssh.connect(
            hostname=host,
            username=username,
            password=password,
            key_filename=key_filename,
            timeout=10
        )
        
        stdin, stdout, stderr = ssh.exec_command(command)
        out = stdout.read().decode('utf-8')
        err = stderr.read().decode('utf-8')
        ssh.close()
        
        if err and not out:
            return f"SSH Error: {err}"
        return out
    except Exception as e:
        return f"SSH connection failed: {str(e)}"

# --- Kubernetes Tools ---

def k8s_get_status(namespace: str, pod_name: str = None) -> str:
    """Gets Kubernetes pod status in the specified namespace."""
    if os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock K8s] Fetching status...")
        if pod_name:
            return f"NAME: {pod_name}\nREADY: 0/1\nSTATUS: CrashLoopBackOff\nRESTARTS: 5\nAGE: 2h"
        return f"NAME\tREADY\tSTATUS\tRESTARTS\tAGE\nweb-pod-xyz\t0/1\tCrashLoopBackOff\t5\t2h\ndb-pod-abc\t1/1\tRunning\t0\t5d"

    # Real execution
    cmd = ["kubectl", "get", "pods", "-n", namespace]
    if pod_name:
        cmd.append(pod_name)
    return run_local_command(cmd)

def k8s_get_logs(namespace: str, pod_name: str) -> str:
    """Gets Kubernetes pod logs."""
    if os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock K8s] Fetching logs...")
        return (
            "2026-05-29 01:00:00 [INFO] Starting up server...\n"
            "2026-05-29 01:00:01 [INFO] Connecting to database...\n"
            "2026-05-29 01:00:03 [ERROR] Database connection failed: Connection refused by 10.96.20.10:5432\n"
            "2026-05-29 01:00:03 [FATAL] Exiting server due to database unavailability."
        )

    # Real execution
    cmd = ["kubectl", "logs", pod_name, "-n", namespace, "--tail=100"]
    return run_local_command(cmd)

def k8s_restart_pod(namespace: str, pod_name: str) -> str:
    """Restarts a Kubernetes pod by deleting it (K8s will recreate it)."""
    if os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock K8s] Restarting pod...")
        return f"Mock: Pod {namespace}/{pod_name} successfully deleted (restarted)."

    cmd = ["kubectl", "delete", "pod", pod_name, "-n", namespace]
    return run_local_command(cmd)

def k8s_scale_deployment(namespace: str, deployment: str, replicas: int) -> str:
    """Scales a deployment to the target number of replicas."""
    if os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock K8s] Scaling deployment...")
        return f"Mock: Deployment {namespace}/{deployment} successfully scaled to {replicas} replicas."

    cmd = ["kubectl", "scale", f"deployment/{deployment}", f"--replicas={replicas}", "-n", namespace]
    return run_local_command(cmd)


# --- Proxmox Tools ---

def get_proxmox_ssh_creds():
    """Retrieves SSH configs for Proxmox node from environment."""
    return {
        "host": os.environ.get("PROXMOX_SSH_HOST"),
        "user": os.environ.get("PROXMOX_SSH_USER", "root"),
        "password": os.environ.get("PROXMOX_SSH_PASSWORD"),
        "key": os.environ.get("PROXMOX_SSH_KEY")
    }

def proxmox_get_status(vmid: str) -> str:
    """Checks LXC container status in Proxmox."""
    creds = get_proxmox_ssh_creds()
    if not creds["host"] or os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock Proxmox] Fetching status for VMID %s...", vmid)
        return f"status: stopped\nname: app-container-{vmid}\nmem: 2048MB\ndisk: 20GB\nrunning: false"

    cmd = f"pct status {vmid}"
    return run_ssh_command(creds["host"], creds["user"], cmd, password=creds["password"], key_filename=creds["key"])

def proxmox_get_disk_space(vmid: str) -> str:
    """Queries disk space for the LXC container."""
    creds = get_proxmox_ssh_creds()
    if not creds["host"] or os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock Proxmox] Fetching disk space for VMID %s...", vmid)
        return (
            "Filesystem      Size  Used Avail Use% Mounted on\n"
            "/dev/loop0       20G   19G  0.2G  99% /\n"
            "none            4.0G     0  4.0G   0% /dev"
        )

    cmd = f"pct exec {vmid} -- df -h /"
    return run_ssh_command(creds["host"], creds["user"], cmd, password=creds["password"], key_filename=creds["key"])

def proxmox_reboot_container(vmid: str) -> str:
    """Reboots a Proxmox LXC container."""
    creds = get_proxmox_ssh_creds()
    if not creds["host"] or os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock Proxmox] Rebooting LXC container %s...", vmid)
        return f"Mock: Container {vmid} successfully rebooted."

    cmd = f"pct reboot {vmid}"
    return run_ssh_command(creds["host"], creds["user"], cmd, password=creds["password"], key_filename=creds["key"])

def proxmox_clean_disk(vmid: str) -> str:
    """Performs common disk cleanup operations inside a Proxmox container."""
    creds = get_proxmox_ssh_creds()
    if not creds["host"] or os.environ.get("MOCK_OPS", "true").lower() == "true":
        logger.info("[Mock Proxmox] Cleaning up disk inside container %s...", vmid)
        return "Mock: Ran 'apt-get clean' and removed temporary files. Disk usage reduced to 75%."

    # Perform cleanup inside LXC
    cleanup_cmd = "pct exec {} -- bash -c 'apt-get clean && rm -rf /tmp/* && rm -rf /var/tmp/*'"
    cmd = cleanup_cmd.format(vmid)
    return run_ssh_command(creds["host"], creds["user"], cmd, password=creds["password"], key_filename=creds["key"])

def send_whatsapp_alert(message_body: str) -> str:
    """Dispatches a WhatsApp alert using the local gateway (if running) or falls back to Twilio."""
    admin_number = os.environ.get("ADMIN_WHATSAPP_NUMBER") or os.environ.get("PHYSICIAN_WHATSAPP_NUMBER")
    
    # 1. Attempt local WhatsApp Web Gateway first (if enabled/running)
    use_local = os.environ.get("USE_LOCAL_WHATSAPP", "true").lower() == "true"
    gateway_url = os.environ.get("LOCAL_WHATSAPP_URL", "http://localhost:5001/send-message")
    
    if use_local:
        try:
            import urllib.request
            import json
            payload = json.dumps({"to": admin_number, "message": message_body}).encode('utf-8')
            req = urllib.request.Request(
                gateway_url,
                data=payload,
                headers={'Content-Type': 'application/json'},
                method='POST'
            )
            # Short timeout to avoid hanging if gateway is offline
            with urllib.request.urlopen(req, timeout=8) as response:
                res_data = json.loads(response.read().decode('utf-8'))
                if res_data.get("success"):
                    logger.info(f"[OpsAgent] Local WhatsApp alert dispatched successfully to: {res_data.get('recipient')}")
                    return f"Alert sent via local gateway (JID: {res_data.get('recipient')})"
        except Exception as e:
            logger.warning(f"[OpsAgent] Local WhatsApp Web Gateway failed or is offline: {str(e)}. Falling back to Twilio...")

    # 2. Twilio Fallback
    account_sid = os.environ.get("TWILIO_ACCOUNT_SID", "AC601e1962dc8417ddb3ae53cd8d865020")
    auth_token = os.environ.get("TWILIO_AUTH_TOKEN", "08a68571a251d6d62f60dc83fc725b5a")
    twilio_from = os.environ.get("TWILIO_WHATSAPP_FROM") or os.environ.get("TWILIO_FROM_NUMBER", "whatsapp:+14155238886")
    
    if not (account_sid and auth_token and twilio_from and admin_number):
        logger.warning("[OpsAgent] Twilio credentials or admin number not set. Skipping WhatsApp alert.")
        return "Twilio credentials not configured."
        
    try:
        from twilio.rest import Client
        client = Client(account_sid, auth_token)
        message = client.messages.create(
            from_=twilio_from,
            body=message_body,
            to=admin_number
        )
        logger.info(f"[OpsAgent] WhatsApp alert sent successfully! SID: {message.sid}")
        return f"Alert sent (SID: {message.sid})"
    except Exception as e:
        logger.error(f"[OpsAgent] Failed to send WhatsApp alert: {str(e)}")
        return f"Failed to send alert: {str(e)}"

