import subprocess
from proxmoxer import ProxmoxAPI
from pve_cloud.lib.validate import raise_on_py_cloud_missmatch

def get_cloud_domain(target_pve):
    avahi_disc = subprocess.run(["avahi-browse", "-rpt", "_pxc._tcp"], stdout=subprocess.PIPE, text=True, check=True)
    services = avahi_disc.stdout.splitlines()

    # find cloud domain hosts and get first online per proxmox cluster
    for service in services:
        if service.startswith("="):
            # avahi service def
            svc_args = service.split(";")
            host_ip = svc_args[7]

            cloud_domain = None
            cluster_name = None

            for txt_arg in svc_args[9].split():
                txt_arg = txt_arg.replace('"', '')
                if txt_arg.startswith("cloud_domain"):
                    cloud_domain = txt_arg.split("=")[1]

                if txt_arg.startswith("cluster_name"):
                    cluster_name = txt_arg.split("=")[1]

            if not cloud_domain or not cluster_name:
                raise ValueError(f"Missconfigured proxmox cloud avahi service: {service}")
            
            if target_pve.endswith(cloud_domain):
                return cloud_domain
            

    raise RuntimeError("Could not get cloud domain via avahi mdns!")


def get_pve_inventory(pve_cloud_domain, skip_py_cloud_validation = False):
    # call avahi-browse -rpt _pxc._tcp and find online host matching pve cloud domain
    # connect via ssh and fetch all other hosts via proxmox api => build inventory
    avahi_disc = subprocess.run(["avahi-browse", "-rpt", "_pxc._tcp"], stdout=subprocess.PIPE, text=True, check=True)
    services = avahi_disc.stdout.splitlines()

    pve_inventory = {}

    # find cloud domain hosts and get first online per proxmox cluster
    cloud_domain_first_hosts = {}
    for service in services:
        if service.startswith("="):
            # avahi service def
            svc_args = service.split(";")
            host_ip = svc_args[7]

            cloud_domain = None
            cluster_name = None

            for txt_arg in svc_args[9].split():
                txt_arg = txt_arg.replace('"', '')
                if txt_arg.startswith("cloud_domain"):
                    cloud_domain = txt_arg.split("=")[1]

                if txt_arg.startswith("cluster_name"):
                    cluster_name = txt_arg.split("=")[1]

            if not cloud_domain or not cluster_name:
                raise ValueError(f"Missconfigured proxmox cloud avahi service: {service}")
            
            # main pve cloud inventory
            if cloud_domain == pve_cloud_domain and cluster_name not in cloud_domain_first_hosts:
                if not skip_py_cloud_validation:
                    raise_on_py_cloud_missmatch(host_ip) # validate that versions of dev machine and running on cluster match

                cloud_domain_first_hosts[cluster_name] = host_ip
            
    # iterate over hosts and build pve inv via proxmox api
    for cluster_first, first_host in cloud_domain_first_hosts.items():
        proxmox = ProxmoxAPI(
            first_host, user="root", backend='ssh_paramiko'
        )

        cluster_name = None
        status_resp = proxmox.cluster.status.get()
        for entry in status_resp:
            if entry['id'] == "cluster":
                cluster_name = entry['name']
            break

        if cluster_name is None:
            raise RuntimeError("Could not get cluster name")
        
        if cluster_name != cluster_first:
            raise ValueError(f"Proxmox cluster name missconfigured in avahi service {cluster_name}/{cluster_first}")
        
        pve_inventory[cluster_name] = {}

        # fetch other hosts via api
        cluster_hosts = proxmox.nodes.get()

        for node in cluster_hosts:
            node_name = node["node"]

            if node["status"] == "offline":
                print(f"skipping offline node {node_name}")
                continue
            
            # get the main ip
            ifaces = proxmox.nodes(node_name).network.get()
            node_ip_address = None
            for iface in ifaces:
                if 'gateway' in iface:
                    if node_ip_address is not None:
                        raise RuntimeError(f"found multiple ifaces with gateways for node {node_name}")
                    node_ip_address = iface.get("address")

            if node_ip_address is None:
                raise RuntimeError(f"Could not find ip for node {node_name}")
            
            pve_inventory[cluster_name][node_name] = {
                "ansible_user": "root",
                "ansible_host": node_ip_address
            }
                    

    return pve_inventory