"""Characterization test for the slides (TV slideshow) plugin feed.

The slide manager rework moved the public playlist to /api/slides/feed with a
flat (non-enveloped) response shape so the screensaver's existing parser needs
no change. Pin that contract here.
"""


def test_slides_feed_shape(client, db):
    """GET /api/slides/feed returns a flat playlist for a surface (no auth)."""
    resp = client.get('/api/slides/feed?surface=lobby')
    assert resp.status_code == 200
    data = resp.get_json()
    assert data['success'] is True
    assert data['surface'] == 'lobby'
    assert isinstance(data['slides'], list)
    assert data['basepath'] == '/api/slides/img/lobby/'
    assert 'interval' in data


def test_slides_feed_unknown_surface_falls_back(client, db):
    """An invalid surface name falls back to lobby instead of erroring."""
    resp = client.get('/api/slides/feed?surface=../etc')
    assert resp.status_code == 200
    assert resp.get_json()['surface'] == 'lobby'


# ---------------------------------------------------------------------------
# Management routes are gated on the slides.manage permission (both surfaces).
# A curator role holding it works without full admin; auth alone does not.
# ---------------------------------------------------------------------------

def _headers_for(client, username, password):
    resp = client.post('/api/auth/login',
                       json={'username': username, 'password': password})
    assert resp.status_code == 200, f'Login failed: {resp.get_json()}'
    return {'Authorization': f"Bearer {resp.get_json()['data']['access_token']}"}


def test_slides_manage_requires_permission(client, db):
    """Authenticated but permission-less user cannot list slides (403)."""
    from werkzeug.security import generate_password_hash
    from shopdb.core.models import User

    user = User(username='plainuser', email='plain@test.local',
                passwordhash=generate_password_hash('testpass'))
    db.session.add(user)
    db.session.commit()

    resp = client.get('/api/slides/lobby',
                      headers=_headers_for(client, 'plainuser', 'testpass'))
    assert resp.status_code == 403


def test_slides_manage_curator_allowed(client, db):
    """A non-admin role holding slides.manage can reach the management routes."""
    from werkzeug.security import generate_password_hash
    from shopdb.core.models import User, Role, Permission

    perm = Permission(name='slides.manage',
                      description='Manage lobby display and screensaver slides',
                      category='slides')
    role = Role(rolename='slidecurator', description='Slide curator')
    role.permissions.append(perm)
    db.session.add_all([perm, role])
    db.session.flush()

    user = User(username='curator', email='curator@test.local',
                passwordhash=generate_password_hash('testpass'))
    user.roles.append(role)
    db.session.add(user)
    db.session.commit()

    headers = _headers_for(client, 'curator', 'testpass')

    # The login payload advertises the permission to the frontend authStore.
    login = client.post('/api/auth/login',
                        json={'username': 'curator', 'password': 'testpass'})
    assert 'slides.manage' in login.get_json()['data']['user']['permissions']

    # And the management route is reachable (200, not 403).
    resp = client.get('/api/slides/lobby', headers=headers)
    assert resp.status_code == 200


def test_slides_manage_admin_allowed(client, db, auth_headers):
    """Admin keeps access via the require_permission admin bypass."""
    resp = client.get('/api/slides/lobby', headers=auth_headers)
    assert resp.status_code == 200
