"""exercise_rich_text: §11 Normalisierung und ID-Sammlung."""

from __future__ import annotations

import pytest
from fastapi import HTTPException
from unittest.mock import MagicMock

from exercise_rich_text import (
    assert_no_inline_media_references_on_create,
    collect_inline_exercise_media_ids,
    normalize_inline_exercise_media_markup,
    validate_inline_exercise_media_ids_for_exercise,
)


def test_normalize_curly_to_span() -> None:
    s = '<p>Vor {{exerciseMedia: 42 }} nach</p>'
    out = normalize_inline_exercise_media_markup(s)
    assert 'data-shinkan-exercise-media="42"' in out
    assert 'data-shinkan-exercise-media-size="medium"' in out
    assert "{{" not in out


def test_collect_merges_braces_and_data_attr() -> None:
    html = '{{ExercisemEDIA: 1}}\n<span data-shinkan-exercise-media="2"></span>'
    assert collect_inline_exercise_media_ids(html) == {1, 2}


def test_assert_no_inline_on_create_raises() -> None:
    with pytest.raises(HTTPException) as ei:
        assert_no_inline_media_references_on_create({5})
    assert ei.value.status_code == 400
    body = ei.value.detail
    assert isinstance(body, dict)
    assert body["code"] == "INLINE_EXERCISE_MEDIA_ON_CREATE"


def test_validate_ids_sql_mock() -> None:
    mock_cur = MagicMock()
    mock_cur.fetchall.return_value = [{"id": 1}]
    with pytest.raises(HTTPException) as ei:
        validate_inline_exercise_media_ids_for_exercise(mock_cur, 100, {1, 99})
    assert ei.value.detail["invalid_exercise_media_ids"] == [99]
