import pytest
from src.app import app, db, User, Note, blacklist # Import app, db, User, Note, blacklist
from werkzeug.security import generate_password_hash

@pytest.fixture(scope='module')
def test_client():
    app.config['TESTING'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' # Set the URI here
    app.config['JWT_SECRET_KEY'] = 'test-secret-key'
    app.config['JWT_ACCESS_TOKEN_EXPIRES'] = 1 # 1 second for testing

    with app.test_client() as client:
        with app.app_context(): # Push an app context for the module
            db.create_all()
            yield client
            db.session.remove()
            db.drop_all()

@pytest.fixture(scope='function')
def init_database():
    # This fixture will run within the app context established by test_client (module scope)
    # So no need to push/pop another app_context here.
    db.session.remove() # Clear session before each test
    db.drop_all() # Drop all tables
    db.create_all() # Recreate tables
    blacklist.clear() # Clear blacklist for each test
    yield db
    db.session.remove() # Clean up session after each test
    db.drop_all() # Drop tables again

def test_register_user(test_client, init_database):
    response = test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test@example.com', 'password': 'password123'})
    assert response.status_code == 201
    assert 'User created successfully' in response.json['msg']

    user = User.query.filter_by(username='testuser').first()
    assert user is not None
    assert user.email == 'test@example.com'

def test_register_existing_user(test_client, init_database):
    test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test@example.com', 'password': 'password123'})
    response = test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test2@example.com', 'password': 'password123'})
    assert response.status_code == 409
    assert 'Username already exists' in response.json['msg']

def test_login_user(test_client, init_database):
    test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test@example.com', 'password': 'password123'})
    response = test_client.post('/api/auth/login', json={'username': 'testuser', 'password': 'password123'})
    assert response.status_code == 200
    assert 'access_token' in response.json

def test_login_invalid_password(test_client, init_database):
    test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test@example.com', 'password': 'password123'})
    response = test_client.post('/api/auth/login', json={'username': 'testuser', 'password': 'wrongpassword'})
    assert response.status_code == 401
    assert 'Bad username or password' in response.json['msg']

def test_login_non_existent_user(test_client, init_database):
    response = test_client.post('/api/auth/login', json={'username': 'nonexistent', 'password': 'password123'})
    assert response.status_code == 401
    assert 'Bad username or password' in response.json['msg']

def test_logout_user(test_client, init_database):
    test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test@example.com', 'password': 'password123'})
    login_response = test_client.post('/api/auth/login', json={'username': 'testuser', 'password': 'password123'})
    access_token = login_response.json['access_token']

    logout_response = test_client.post('/api/auth/logout', headers={'Authorization': f'Bearer {access_token}'})
    assert logout_response.status_code == 200
    assert 'Successfully logged out' in logout_response.json['msg']

    # Try to access protected route with blacklisted token
    protected_response = test_client.get('/api/notes', headers={'Authorization': f'Bearer {access_token}'})
    assert protected_response.status_code == 422 # Changed to 422

def test_protected_route_access(test_client, init_database):
    test_client.post('/api/auth/register', json={'username': 'testuser', 'email': 'test@example.com', 'password': 'password123'})
    login_response = test_client.post('/api/auth/login', json={'username': 'testuser', 'password': 'password123'})
    access_token = login_response.json['access_token']

    response = test_client.get('/api/notes', headers={'Authorization': f'Bearer {access_token}'})
    assert response.status_code == 200 # Should be 200 if no notes, or 201 if creating

def test_protected_route_no_token(test_client, init_database):
    response = test_client.get('/api/notes')
    assert response.status_code == 422 # Changed to 422

def test_protected_route_invalid_token(test_client, init_database):
    response = test_client.get('/api/notes', headers={'Authorization': 'Bearer invalid_token'})
    assert response.status_code == 422 # Changed to 422
