"""Tests for notificationtypes.boardcategory (shared row on the shopfloor board).

The board grouped cards by display style alone, so every type set to grid landed
in the Recertification row and every carousel type in Recognition's, under a
heading naming someone else's type. Each type now gets a row of its own, and
this column is the opt-in for the other direction: Change, Awareness and
Incident share one row under a category name.

The grouping itself is frontend (ShopfloorDashboard.vue); what is pinned here is
the contract it groups on - the feed must carry boardcategory per card, and the
type API must round-trip it.
"""

from plugins.notifications.models import Notification, NotificationType


def _make_type(db, typename, displaystyle='grid', boardcategory=None):
    t = NotificationType(typename=typename, typecolor='#17a2b8', isactive=True,
                         displaystyle=displaystyle, boardcategory=boardcategory)
    db.session.add(t)
    db.session.commit()
    return t


def _make_note(db, ntype, text):
    n = Notification(notificationtypeid=ntype.notificationtypeid,
                     notification=text, businessunitid=None,
                     isactive=True, isshopfloor=True)
    db.session.add(n)
    db.session.commit()
    return n


def _current(client):
    resp = client.get('/api/notifications/shopfloor')
    assert resp.status_code == 200, resp.get_json()
    return resp.get_json()['data']['current']


def test_feed_carries_the_category_per_card(client, db):
    """The dashboard groups on this field, so it has to reach the card."""
    ntype = _make_type(db, 'Awareness', boardcategory='Alerts')
    _make_note(db, ntype, 'watch your step')

    card = _current(client)[0]
    assert card['boardcategory'] == 'Alerts'
    assert card['typename'] == 'Awareness'
    assert card['displaystyle'] == 'grid'


def test_uncategorised_type_reports_an_empty_category(client, db):
    """Blank, not null: the dashboard falls back to the type name for a row."""
    ntype = _make_type(db, 'Recertification')
    _make_note(db, ntype, 'forklift cert due')

    assert _current(client)[0]['boardcategory'] == ''


def test_types_sharing_a_category_keep_their_own_names(client, db):
    """Grouping is the dashboard's job; the feed must not flatten the types."""
    change = _make_type(db, 'Change', boardcategory='Alerts')
    incident = _make_type(db, 'Incident', boardcategory='Alerts')
    _make_note(db, change, 'line 3 retooling')
    _make_note(db, incident, 'press 12 down')

    cards = _current(client)
    assert {c['typename'] for c in cards} == {'Change', 'Incident'}
    assert {c['boardcategory'] for c in cards} == {'Alerts'}


def test_api_round_trips_the_category(client, db, auth_headers):
    create = client.post('/api/notifications/types',
                         json={'typename': 'Awareness', 'displaystyle': 'grid',
                               'boardcategory': 'Alerts'},
                         headers=auth_headers)
    assert create.status_code in (200, 201), create.get_json()
    typeid = create.get_json()['data']['notificationtypeid']
    assert create.get_json()['data']['boardcategory'] == 'Alerts'

    listed = client.get('/api/notifications/types', headers=auth_headers)
    row = next(t for t in listed.get_json()['data']
               if t['notificationtypeid'] == typeid)
    assert row['boardcategory'] == 'Alerts'


def test_blank_category_stores_as_null_not_an_empty_group(client, db, auth_headers):
    """Every uncategorised type sharing the empty string would be one big row."""
    create = client.post('/api/notifications/types',
                         json={'typename': 'Solo', 'boardcategory': '   '},
                         headers=auth_headers)
    assert create.status_code in (200, 201), create.get_json()
    typeid = create.get_json()['data']['notificationtypeid']

    stored = db.session.get(NotificationType, typeid)
    assert stored.boardcategory is None
    assert create.get_json()['data']['boardcategory'] == ''


def test_api_rejects_an_overlong_category(client, db, auth_headers):
    resp = client.post('/api/notifications/types',
                       json={'typename': 'Bad', 'boardcategory': 'x' * 51},
                       headers=auth_headers)

    assert resp.status_code == 400
    assert 'boardcategory' in resp.get_data(as_text=True)


def test_category_change_moves_the_config_version(client, db, auth_headers):
    """Open kiosks reload on a layout change; a re-grouped board is one."""
    ntype = _make_type(db, 'Awareness')
    before = client.get('/api/notifications/shopfloor').get_json()['data']['configversion']

    client.put(f'/api/notifications/types/{ntype.notificationtypeid}',
               json={'boardcategory': 'Alerts'}, headers=auth_headers)

    after = client.get('/api/notifications/shopfloor').get_json()['data']['configversion']
    assert before != after
