"""Machines list search covers the columns the list actually shows.

The table displays Machine #, Name, Serial Number, Type and Vendor, so all of
them must be searchable. Searching a type name ('Part Washer') used to return
zero rows because the filter only looked at the asset fields.
"""

from shopdb.extensions import db as _db
from shopdb.core.models import Asset, AssetType
from shopdb.core.models.vendor import Vendor

from plugins.machines.models import Machine, MachineType


def _seed_machines():
    """Two machines: one Part Washer by Acme, one Lathe with no type or vendor.

    The typeless machine guards the outer joins - it must still be findable by
    its own asset fields.
    """
    assettype = AssetType(assettype='machine')
    _db.session.add(assettype)
    _db.session.flush()

    washertype = MachineType(machinetype='Part Washer')
    lathe_vendor = Vendor(vendor='Acme Industrial')
    _db.session.add_all([washertype, lathe_vendor])
    _db.session.flush()

    washer_asset = Asset(assetnumber='0410', name='Cell 4 washer',
                         serialnumber='SN-WASH-1', assettypeid=assettype.assettypeid)
    plain_asset = Asset(assetnumber='0999', name='Old lathe',
                        serialnumber='SN-LATHE-9', assettypeid=assettype.assettypeid)
    _db.session.add_all([washer_asset, plain_asset])
    _db.session.flush()

    _db.session.add_all([
        Machine(assetid=washer_asset.assetid,
                machinetypeid=washertype.machinetypeid,
                vendorid=lathe_vendor.vendorid),
        Machine(assetid=plain_asset.assetid),
    ])
    _db.session.commit()


def _numbers(resp):
    return sorted(item['assetnumber'] for item in resp.get_json()['data'])


def test_search_matches_machine_type_name(client, db):
    _seed_machines()

    resp = client.get('/api/machines?search=Part Washer')

    assert resp.status_code == 200, resp.get_json()
    assert _numbers(resp) == ['0410']


def test_search_matches_vendor_name(client, db):
    _seed_machines()

    resp = client.get('/api/machines?search=Acme')

    assert resp.status_code == 200, resp.get_json()
    assert _numbers(resp) == ['0410']


def test_search_still_matches_asset_fields(client, db):
    _seed_machines()

    for term, expected in [('0999', ['0999']),
                           ('Old lathe', ['0999']),
                           ('SN-WASH', ['0410'])]:
        resp = client.get(f'/api/machines?search={term}')
        assert resp.status_code == 200, resp.get_json()
        assert _numbers(resp) == expected, term


def test_search_does_not_drop_machines_without_type_or_vendor(client, db):
    """The outer joins must not turn into inner joins."""
    _seed_machines()

    resp = client.get('/api/machines?search=lathe')

    assert resp.status_code == 200, resp.get_json()
    assert _numbers(resp) == ['0999']


def test_search_miss_returns_empty(client, db):
    _seed_machines()

    resp = client.get('/api/machines?search=zzzznotathing')

    assert resp.status_code == 200, resp.get_json()
    assert _numbers(resp) == []
