"""Smoke tests pinning the baseline behavior of shopdb-flask.

These eight tests are the safety net required before any structural
refactor proceeds.
"""

import pytest


def test_app_factory_creates_app(app):
    """create_app('testing') returns a Flask app with TESTING=True."""
    assert app is not None
    assert app.config['TESTING'] is True
    assert 'sqlite' in app.config['SQLALCHEMY_DATABASE_URI']


def test_login_with_valid_credentials_returns_tokens(client, admin_user):
    """POST /api/auth/login with valid creds returns access and refresh tokens."""
    response = client.post(
        '/api/auth/login',
        json={'username': 'testadmin', 'password': 'testpass'},
    )
    assert response.status_code == 200
    payload = response.get_json()
    assert 'data' in payload
    data = payload['data']
    assert 'access_token' in data
    assert 'refresh_token' in data
    assert 'user' in data
    assert data['user']['username'] == 'testadmin'


def test_login_with_invalid_credentials_returns_401(client, admin_user):
    """Wrong password returns 401 with the documented error envelope.

    Pins the current shape: error info nested under `data.error` (not at
    top level). The error_response docstring claims top-level `error` but
    the implementation puts it under `data`. Pinned as-is until that
    inconsistency is intentionally addressed.
    """
    response = client.post(
        '/api/auth/login',
        json={'username': 'testadmin', 'password': 'wrongpassword'},
    )
    assert response.status_code == 401
    payload = response.get_json()
    assert payload['status'] == 'error'
    assert payload['data']['error']['code'] == 'UNAUTHORIZED'


def test_login_with_missing_fields_returns_400(client):
    """Missing username or password returns 400 validation error."""
    response = client.post('/api/auth/login', json={})
    assert response.status_code == 400


def test_protected_route_requires_authentication(client, admin_user):
    """GET /api/users without a JWT returns 401."""
    response = client.get('/api/users')
    assert response.status_code == 401


def test_protected_route_works_with_jwt(client, auth_headers):
    """GET /api/users with a valid JWT returns 200."""
    response = client.get('/api/users', headers=auth_headers)
    assert response.status_code == 200


def test_paginated_response_shape(client, auth_headers):
    """A paginated list endpoint returns data plus pagination meta.

    Uses /api/locations because it is a simple platform endpoint that
    uses paginated_response. Pagination meta keys follow the naming
    convention (lowercase concatenated): page, perpage, total,
    totalpages, hasnext, hasprev.
    """
    response = client.get('/api/locations', headers=auth_headers)
    assert response.status_code == 200
    payload = response.get_json()
    assert 'data' in payload
    assert isinstance(payload['data'], list)
    assert 'meta' in payload
    assert 'pagination' in payload['meta']
    pagination = payload['meta']['pagination']
    assert 'page' in pagination
    assert 'perpage' in pagination
    assert 'total' in pagination
    assert 'totalpages' in pagination


def test_plugin_loader_discovers_bundled_plugins(app):
    """Plugin manager finds the bundled plugins."""
    from shopdb.plugins import plugin_manager

    expected_plugins = {
        'computers',
        'employees',
        'knowledgebase',
        'machines',
        'network',
        'notifications',
        'printers',
        'slides',
        'usb',
    }

    with app.app_context():
        loader = plugin_manager.loader
        discovered = set(loader.discover_plugins())

    assert expected_plugins.issubset(discovered), (
        f'Missing bundled plugins: {expected_plugins - discovered}'
    )
