"""An in-memory Docker boundary for allocator tests; no daemon is contacted."""
import copy
import hashlib
import ipaddress
from contextlib import nullcontext

from network_runtime import NetworkFailure


def config(project, settings=None):
    network = {'name': project + '_default', **(settings or {})}
    return {'name': project, 'services': {'api': {'networks': {'default': {}}}}, 'networks': {'default': network}}


def network(project, subnet, **settings):
    return {'Id': hashlib.sha256(project.encode()).hexdigest(), 'Name': project + '_default', 'Driver': 'bridge',
            'Scope': 'local', 'Internal': False, 'Attachable': False, 'EnableIPv6': False,
            'IPAM': {'Driver': 'default', 'Options': {},
                     'Config': [{'Subnet': subnet, 'Gateway': str(ipaddress.IPv4Network(subnet).network_address + 1)}]},
            'Options': {},
            'Labels': {'com.docker.compose.project': project, 'com.docker.compose.network': 'default'},
            'Containers': {}, **settings}


class Host:
    def __init__(self):
        self.networks = [network('unrelated', '172.28.0.0/24')]
        self.calls = []
        self.pool_failure = ''
        self.lose_reply = False
        self.compose_version = '2.39.4'

    def inventory(self, command, require_pools=True):
        return {'docker_version': '28.0.4', 'compose_version': self.compose_version, 'observed_at': '2026-09-15T00:00:00Z',
                'python_version': '3.8.20', 'pool_source': 'fixture', 'pool_failure': self.pool_failure,
                'pools': [{'base': '172.28.0.0/22', 'size': 16}], 'networks': copy.deepcopy(self.networks),
                'host_excluded': [], 'host_records': [],
                'excluded': [n['IPAM']['Config'][0]['Subnet'] for n in self.networks]}

    def ownership(self, command, selected):
        return {'networks': copy.deepcopy(self.networks)}

    def command(self, argv, seconds=10):
        self.calls.append(argv)
        labels = dict(v.split('=', 1) for i, v in enumerate(argv) if i and argv[i - 1] == '--label')
        subnet = argv[argv.index('--subnet') + 1]
        name = argv[-1]
        observed = network(labels['com.docker.compose.project'], subnet, Labels=labels, Name=name,
                           Internal='--internal' in argv, Attachable='--attachable' in argv)
        self.networks.append(observed)
        if self.lose_reply:
            self.lose_reply = False
            raise NetworkFailure('network_command_unavailable')
        return observed['Id'].encode()

    def arguments(self, lock=nullcontext):
        return {'reader': self.inventory, 'owner_reader': self.ownership, 'command': self.command, 'lock': lock}
