import re

import pytest
from asgiref.sync import sync_to_async
from django.conf import settings
from django.test.client import AsyncClient  # type: ignore
from django.urls import reverse

from promptgame.gameui.user_account_tools import create_user_and_account
from promptgame.tests.helpers import async_login


@pytest.mark.asyncio
@pytest.mark.django_db
@pytest.mark.parametrize(
    "field_name, target_length",
    [
        ("attacker_input", settings.MAX_ATTACK_LENGTH_TOKENS),
        ("defense_pre_prompt", settings.MAX_DEFENSE_PRE_PROMPT_LENGTH_TOKENS),
        ("defense_post_prompt", settings.MAX_DEFENSE_POST_PROMPT_LENGTH_TOKENS),
        ("access_code", settings.MAX_ACCESS_CODE_LENGTH_TOKENS),
    ],
)
async def test_check_token_length(
    async_client: AsyncClient,
    field_name: str,
    target_length: int,
) -> None:
    """Check that defense creation fails if token limits exceeded"""
    user, _ = await sync_to_async(create_user_and_account)()
    await async_login(user, async_client)

    form_value = {
        "field_name": field_name,
        field_name: "",
    }

    # too many tokens in attack input (should say >=target_length in red)
    form_value[field_name] = " a" * (1 + target_length)
    resp = await async_client.post(
        reverse("check_token_length"),
        form_value,
    )
    resp_content = resp.content.decode("utf8")
    assert re.match(
        rf""".*text-red-500">\s*&ge;\s*{target_length}\s*<.*""", resp_content
    )

    # exactly limit amount of tokens in attack input (should be target_length in green)
    form_value[field_name] = " a" * target_length
    resp = await async_client.post(
        reverse("check_token_length"),
        form_value,
    )
    resp_content = resp.content.decode("utf8")
    assert re.match(rf""".*text-green-600">\s*{target_length}\s*<.*""", resp_content)

    # less than limit amount of tokens in attack input (should in green)
    form_value[field_name] = " a" * (target_length // 2)
    resp = await async_client.post(
        reverse("check_token_length"),
        form_value,
    )
    resp_content = resp.content.decode("utf8")
    assert """text-green-600""" in resp_content
