from ipaddress import ip_network

from bundlewrap.exceptions import NoSuchNode
from bundlewrap.metadata import atomic

defaults = {
    'apt': {
        'packages': {
            'bird2': {
                'needed_by': {
                    'svc_systemd:bird',
                },
            },
        },
    },
    'pacman': {
        'packages': {
            'bird': {
                'needed_by': {
                    'svc_systemd:bird',
                },
            },
        },
    },
    'sysctl': {
        'options': {
            'net.ipv4.conf.all.forwarding': '1',
            'net.ipv6.conf.all.forwarding': '1',
        },
    },
}

@metadata_reactor.provides(
    'bird/bgp_neighbors',
)
def neighbor_info_from_wireguard(metadata):
    neighbors = {}
    my_as = repo.libs.s2s.AS_NUMBERS[metadata.get('location')]

    for name, config in metadata.get('wireguard/peers', {}).items():
        try:
            rnode = repo.get_node(name)
        except NoSuchNode:
            continue

        if not rnode.has_bundle('bird'):
            continue

        neighbors[name] = {
            'local_ip': config['my_ip'],
            'local_as': my_as,
            'neighbor_ip': config['their_ip'],
            'neighbor_as': repo.libs.s2s.AS_NUMBERS[rnode.metadata.get('location')],
        }

    return {
        'bird': {
            'bgp_neighbors': neighbors,
        },
    }


@metadata_reactor.provides(
    'bird/my_ip',
)
def my_ip(metadata):
    if node.has_bundle('wireguard'):
        wg_ifaces = sorted({iface for iface in metadata.get('interfaces').keys() if iface.startswith('wg_')})
        if not wg_ifaces:
            return {}
        my_ip = sorted(metadata.get(f'interfaces/{wg_ifaces[0]}/ips'))[0].split('/')[0]
    else:
        my_ip = str(sorted(repo.libs.tools.resolve_identifier(repo, node.name))[0])

    return {
        'bird': {
            'my_ip': my_ip,
        },
    }


@metadata_reactor.provides(
    'firewall/port_rules',
)
def firewall(metadata):
    sources = set()
    for config in metadata.get('bird/bgp_neighbors', {}).values():
        sources.add(config['neighbor_ip'])

    return {
        'firewall': {
            'port_rules': {
                '179/tcp': atomic(sources),
            },
        },
    }
