"""Deleting a relationship is soft, and everything that reads them must know.

Rows are retired with isactive = False, never removed, and assetrelationships is
unique on (source, target, type). Anything that looks a relationship up without
filtering on isactive therefore sees links the UI does not show - and refuses to
create one it cannot create any other way, or retires the last live row believing
another one covers it.
"""

import pytest

from shopdb.core.models import Asset, AssetType
from shopdb.core.models.relationship import RelationshipType, AssetRelationship


@pytest.fixture
def rig(db):
    if not AssetType.query.filter_by(assettype='computer').first():
        db.session.add(AssetType(assettype='computer'))
    if not AssetType.query.filter_by(assettype='machine').first():
        db.session.add(AssetType(assettype='machine'))
    controls = RelationshipType.query.filter_by(relationshiptype='controls').first()
    if not controls:
        controls = RelationshipType(relationshiptype='controls', isdirectional=True)
        db.session.add(controls)
    controls.isdirectional = True
    db.session.commit()
    computer = AssetType.query.filter_by(assettype='computer').first()
    machine = AssetType.query.filter_by(assettype='machine').first()
    pc = Asset(assetnumber='PCSOFT01', assettypeid=computer.assettypeid)
    bay = Asset(assetnumber='BAYSOFT01', assettypeid=machine.assettypeid)
    db.session.add_all([pc, bay])
    db.session.commit()
    return {'pc': pc, 'bay': bay, 'controls': controls}


def _create(client, headers, source, target, typeid):
    return client.post('/api/assets/relationships',
                       json={'sourceassetid': source, 'targetassetid': target,
                             'relationshiptypeid': typeid},
                       headers=headers)


def test_a_deleted_relationship_can_be_created_again(client, db, rig, auth_headers):
    """Soft delete then re-add answered 409 about a link nothing displayed."""
    created = _create(client, auth_headers, rig['pc'].assetid, rig['bay'].assetid,
                      rig['controls'].relationshiptypeid)
    assert created.status_code == 201, created.get_json()
    relid = created.get_json()['data']['relationshipid']

    assert client.delete('/api/assets/relationships/%d' % relid,
                         headers=auth_headers).status_code == 200

    again = _create(client, auth_headers, rig['pc'].assetid, rig['bay'].assetid,
                    rig['controls'].relationshiptypeid)
    assert again.status_code in (200, 201), again.get_json()
    row = db.session.get(AssetRelationship, relid)
    assert row.isactive is True
    assert AssetRelationship.query.filter_by(
        sourceassetid=rig['pc'].assetid,
        targetassetid=rig['bay'].assetid).count() == 1


def test_a_deleted_inverse_does_not_block_the_right_direction(
        client, db, rig, auth_headers):
    """'Remove the existing one first' is the advice the guard itself gives."""
    wrong = _create(client, auth_headers, rig['bay'].assetid, rig['pc'].assetid,
                    rig['controls'].relationshiptypeid)
    assert wrong.status_code == 201
    relid = wrong.get_json()['data']['relationshipid']
    assert client.delete('/api/assets/relationships/%d' % relid,
                         headers=auth_headers).status_code == 200

    right = _create(client, auth_headers, rig['pc'].assetid, rig['bay'].assetid,
                    rig['controls'].relationshiptypeid)
    assert right.status_code in (200, 201), right.get_json()
