import pytest
from fastapi import HTTPException


def test_classes_school_students_route_registered_before_dynamic_class_id():
    from routers.database.tools.classes_router import router

    paths = [route.path for route in router.routes]
    assert paths.index('/school/students') < paths.index('/{class_id}')


def test_supabase_anon_for_user_sets_user_authorization_header(monkeypatch):
    from modules.database.supabase.utils import client as client_module

    captured = {}

    def fake_create_client(url, key, options=None):
        captured['url'] = url
        captured['key'] = key
        captured['options'] = options
        return object()

    monkeypatch.setenv('SUPABASE_URL', 'http://supabase.test')
    monkeypatch.setenv('ANON_KEY', 'anon-key')
    monkeypatch.setattr(client_module, 'create_client', fake_create_client)

    client_module.SupabaseAnonClient.for_user('Bearer user-jwt')

    # apikey comes from the `key` arg (supabase-py sets the apikey header); options.headers must
    # carry only the user Authorization override. A second apikey here → Kong "Duplicate API key".
    assert captured['key'] == 'anon-key'
    assert 'apikey' not in captured['options'].headers
    assert captured['options'].headers['Authorization'] == 'Bearer user-jwt'


@pytest.mark.parametrize('token', ['', '   '])
def test_supabase_anon_for_user_requires_token(token):
    from modules.database.supabase.utils.client import SupabaseAnonClient

    with pytest.raises(ValueError):
        SupabaseAnonClient.for_user(token)


def test_tldraw_malformed_snapshot_falls_back_to_default():
    from routers.database.tools import tldraw_supabase_storage as storage

    assert not storage._is_valid_tldraw_snapshot({'document': {}, 'session': {}})
    default = storage.create_default_tldraw_content()
    assert storage._is_valid_tldraw_snapshot(default)
    assert default['document']['schema']['schemaVersion'] == 2


def test_tldraw_rejects_cross_tenant_snapshot_db(monkeypatch):
    from routers.database.tools import tldraw_supabase_storage as storage

    monkeypatch.setattr(storage, '_user_scope', lambda user_id: {
        'user_id': user_id,
        'teacher_db': f"cc.users.teacher.{user_id.replace('-', '')}",
        'institute_id': 'school-1',
        'institute_db': 'cc.institutes.allowed',
        'curriculum_db': 'cc.institutes.allowed.curriculum',
    })

    with pytest.raises(HTTPException) as exc:
        storage._authorize_snapshot_path(
            'cc.public.snapshots/School/other-school',
            'cc.institutes.other',
            {'sub': 'user-1'},
            write=False,
        )
    assert exc.value.status_code == 403


def test_graph_node_children_rejects_unscoped_db(monkeypatch):
    from routers.database.tools import graph_tree_router

    monkeypatch.setattr(graph_tree_router, '_allowed_neo4j_dbs', lambda user_id, email: {'cc.users.teacher.user1'})

    with pytest.raises(HTTPException) as exc:
        graph_tree_router._require_allowed_neo4j_db(
            'cc.institutes.not-mine',
            'SubjectClass',
            'classes',
            'user-1',
            'teacher@example.test',
        )
    assert exc.value.status_code == 403


def test_graph_node_children_allows_global_calendar_only():
    from routers.database.tools import graph_tree_router

    graph_tree_router._require_allowed_neo4j_db(
        'classroomcopilot',
        'CalendarYear',
        '',
        'user-1',
        'teacher@example.test',
    )

    with pytest.raises(HTTPException) as exc:
        graph_tree_router._require_allowed_neo4j_db(
            'classroomcopilot',
            'School',
            'school',
            'user-1',
            'teacher@example.test',
        )
    assert exc.value.status_code == 403
