"""Closed public validation for selected-network overlap evidence, with no raw host records."""
import ipaddress

from network_selected import KINDS, LIMIT, REASONS, pool_membership
from network_pools import PRIVATE


def validate_selected(result, network, inventory):
    fields = {'ownership', 'overlap', 'reason', 'pool_membership', 'bridge', 'gateway',
              'self_record_count', 'docker_conflicts', 'host_conflicts'}
    if (not isinstance(result, dict) or set(result) != fields or result['reason'] not in REASONS
            or result['ownership'] not in ('matched', 'unverified')
            or result['overlap'] not in ('clear', 'conflict', 'unverified')
            or result['pool_membership'] not in ('inside_verified_pools', 'outside_verified_pools', 'unverified')
            or type(result['self_record_count']) is not int or not 0 <= result['self_record_count'] <= 16384):
        raise ValueError()
    for field in ('docker_conflicts', 'host_conflicts'):
        if not isinstance(result[field], list) or len(result[field]) > LIMIT:
            raise ValueError()
    if (result['ownership'] == 'matched'
            and network['name'] != inventory['project'] + '_' + network['key']):
        raise ValueError()
    unsupported = result['reason'] in ('selected_ownership_unverified', 'selected_bridge_unsupported')
    if unsupported:
        if (result['overlap'] != 'unverified' or result['bridge'] != '' or result['gateway'] != ''
                or result['self_record_count'] or result['docker_conflicts'] or result['host_conflicts']
                or result['pool_membership'] != 'unverified'):
            raise ValueError()
        if (result['ownership'] == 'unverified') != (result['reason'] == 'selected_ownership_unverified'):
            raise ValueError()
        return
    if (result['ownership'] != 'matched' or network['driver'] != 'bridge'
            or result['bridge'] != 'br-' + network['id'][:12] or not isinstance(result['gateway'], str)
            or len(network['subnets']) != 1):
        raise ValueError()
    subnet = ipaddress.IPv4Network(network['subnets'][0], strict=True)
    gateway = ipaddress.IPv4Address(result['gateway'])
    if (subnet.prefixlen > 30 or not any(subnet.subnet_of(space) for space in PRIVATE)
            or gateway not in subnet or gateway in (subnet.network_address, subnet.broadcast_address)
            or result['pool_membership'] != pool_membership(inventory, subnet)):
        raise ValueError()
    validate_overlaps(result, subnet)


def validate_overlaps(result, subnet):
    for value in result['docker_conflicts']:
        if not isinstance(value, str) or not subnet.overlaps(ipaddress.IPv4Network(value, strict=True)):
            raise ValueError()
    for row in result['host_conflicts']:
        if (not isinstance(row, dict) or set(row) != {'subnet', 'kind', 'device_relation'}
                or not isinstance(row['subnet'], str)
                or row['kind'] not in KINDS
                or row['device_relation'] not in ('selected_bridge', 'foreign_device', 'unattributed')
                or not subnet.overlaps(ipaddress.IPv4Network(row['subnet'], strict=True))):
            raise ValueError()
    conflict = bool(result['docker_conflicts'] or result['host_conflicts'])
    if ((result['overlap'] == 'conflict') != conflict
            or (result['overlap'] == 'clear' and (result['reason'] or result['self_record_count'] < 4))
            or (result['overlap'] == 'unverified' and not result['reason'])):
        raise ValueError()
