"""Network device create/update attaches a primary IP Communication.

Classic network devices carry their IP in the communications table, and the
legacy import needs an HTTP path to set it. The network create/update routes
accept an `ipaddress` and materialize a primary Communication (mirroring the
printer route); GET surfaces it back.
"""

import pytest


@pytest.fixture
def network_setup(db):
    from shopdb.core.models import AssetType, CommunicationType
    db.session.add(AssetType(assettype='network_device', pluginname='network',
                             tablename='networkdevices', description='Network devices'))
    db.session.add(CommunicationType(comtype='IP', description='IP'))
    db.session.commit()


def test_create_network_device_with_ipaddress(client, db, auth_headers, network_setup):
    """POST /api/network with an ipaddress creates a primary Communication and
    echoes the IP back."""
    from shopdb.core.models import Communication
    resp = client.post('/api/network', json={
        'assetnumber': 'SW-CORE-01', 'name': 'Core switch',
        'hostname': 'sw-core-01', 'ipaddress': '10.129.22.101',
    }, headers=auth_headers)
    assert resp.status_code == 201, resp.get_json()
    data = resp.get_json()['data']
    assert data['ipaddress'] == '10.129.22.101'

    assetid = data['assetid']
    comm = Communication.query.filter_by(assetid=assetid, isprimary=True).first()
    assert comm is not None and comm.ipaddress == '10.129.22.101'

    # GET surfaces it too.
    got = client.get(f"/api/network/{data['networkdevice']['networkdeviceid']}",
                     headers=auth_headers)
    assert got.get_json()['data']['ipaddress'] == '10.129.22.101'


def test_update_network_device_ipaddress_upserts(client, db, auth_headers, network_setup):
    """PUT changes the IP in place without creating a second Communication."""
    from shopdb.core.models import Communication
    created = client.post('/api/network', json={
        'assetnumber': 'AP-01', 'name': 'AP', 'ipaddress': '10.0.0.5',
    }, headers=auth_headers).get_json()['data']
    devid = created['networkdevice']['networkdeviceid']

    updated = client.put(f'/api/network/{devid}', json={'ipaddress': '10.0.0.9'},
                         headers=auth_headers)
    assert updated.status_code == 200, updated.get_json()
    assert updated.get_json()['data']['ipaddress'] == '10.0.0.9'

    comms = Communication.query.filter_by(assetid=created['assetid']).all()
    assert len(comms) == 1 and comms[0].ipaddress == '10.0.0.9'


def test_clearing_the_ip_takes_it_back_out(client, db, auth_headers, network_setup):
    """Blanking the form field must clear the stored IP.

    The upsert helper returned early on a blank value, so an address could be
    typed and never removed - invisible until the form grew an IP field.
    """
    from shopdb.core.models import Communication
    created = client.post('/api/network', json={
        'assetnumber': 'SW-09', 'name': 'Switch', 'ipaddress': '10.0.0.5',
    }, headers=auth_headers).get_json()['data']
    devid = created['networkdevice']['networkdeviceid']

    cleared = client.put(f'/api/network/{devid}', json={'ipaddress': ''},
                         headers=auth_headers)
    assert cleared.status_code == 200, cleared.get_json()
    assert not cleared.get_json()['data']['ipaddress']

    comms = Communication.query.filter_by(assetid=created['assetid']).all()
    assert len(comms) == 1 and comms[0].ipaddress is None


def test_omitting_ipaddress_leaves_it_alone(client, db, auth_headers, network_setup):
    """A PUT that never mentions the field must not wipe the stored IP."""
    created = client.post('/api/network', json={
        'assetnumber': 'SW-10', 'name': 'Switch', 'ipaddress': '10.0.0.7',
    }, headers=auth_headers).get_json()['data']
    devid = created['networkdevice']['networkdeviceid']

    updated = client.put(f'/api/network/{devid}', json={'hostname': 'sw-10'},
                         headers=auth_headers)
    assert updated.get_json()['data']['ipaddress'] == '10.0.0.7'


def test_seed_reference_data_creates_ip_commtype(app, db):
    """The reference-data seed now creates the IP communication type the asset
    import depends on."""
    from shopdb.core.models import CommunicationType
    runner = app.test_cli_runner()
    assert runner.invoke(args=['seed', 'reference-data']).exit_code in (0, None)
    with app.app_context():
        assert CommunicationType.query.filter_by(comtype='IP').first() is not None
        assert CommunicationType.query.count() >= 8
