import os

import pytest

from agent_framework.guardrails.calibrated.input_size import (
    _count_tokens,
    _max_tokens,
    verificar_tamanho_input,
)


# ---------------------------------------------------------------------------
# _count_tokens
# ---------------------------------------------------------------------------

def test_count_tokens_texto_vazio():
    assert _count_tokens("") == 1


def test_count_tokens_texto_curto():
    assert _count_tokens("abcd") == 1


def test_count_tokens_estimativa():
    assert _count_tokens("a" * 400) == 100


def test_count_tokens_exato_no_cap():
    # 4096 tokens * 4 chars = 16384 chars → estimativa == 4096
    assert _count_tokens("a" * 16384) == 4096


# ---------------------------------------------------------------------------
# _max_tokens
# ---------------------------------------------------------------------------

def test_max_tokens_default_quando_ausente(monkeypatch):
    monkeypatch.delenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", raising=False)
    assert _max_tokens() == 4096


def test_max_tokens_lido_do_env(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "1000")
    assert _max_tokens() == 1000


def test_max_tokens_invalido_usa_default(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "nao_e_numero")
    assert _max_tokens() == 4096


def test_max_tokens_zero_usa_default(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "0")
    assert _max_tokens() == 4096


def test_max_tokens_negativo_usa_default(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "-100")
    assert _max_tokens() == 4096


# ---------------------------------------------------------------------------
# verificar_tamanho_input — inputs permitidos
# ---------------------------------------------------------------------------

def test_input_curto_passa():
    r = verificar_tamanho_input("qual o valor da minha fatura?")
    assert r.allowed is True
    assert r.code == "INPUT_SIZE"
    assert r.mechanism == "deterministic"
    assert r.data["estimated_tokens"] <= r.data["max_tokens"]


def test_input_vazio_passa():
    r = verificar_tamanho_input("")
    assert r.allowed is True


def test_input_exatamente_no_limite_passa(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "10")
    # 10 tokens * 4 chars = 40 chars → estimativa == 10 (no limite)
    r = verificar_tamanho_input("a" * 40)
    assert r.allowed is True


# ---------------------------------------------------------------------------
# verificar_tamanho_input — inputs bloqueados
# ---------------------------------------------------------------------------

def test_input_gigante_bloqueia():
    texto_grande = "a" * 100_000
    r = verificar_tamanho_input(texto_grande)
    assert r.allowed is False
    assert r.code == "INPUT_SIZE"
    assert r.mechanism == "deterministic"
    assert "excede limite" in r.reason


def test_input_bloqueado_retorna_dados_corretos():
    texto_grande = "x" * 20_000
    r = verificar_tamanho_input(texto_grande)
    assert r.allowed is False
    assert r.data["estimated_tokens"] > r.data["max_tokens"]
    assert r.data["len_chars"] == 20_000


def test_input_um_token_acima_do_cap_bloqueia(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "10")
    # 11 tokens * 4 chars = 44 chars → estimativa == 11 (acima do cap 10)
    r = verificar_tamanho_input("a" * 44)
    assert r.allowed is False


def test_input_bloqueado_preserva_texto_original():
    texto = "a" * 100_000
    r = verificar_tamanho_input(texto)
    assert r.sanitized_text == texto


def test_cap_customizado_via_env(monkeypatch):
    monkeypatch.setenv("TIM_GUARDRAIL_INPUT_MAX_TOKENS", "100")
    texto_medio = "a" * 500  # 125 tokens estimados → acima de 100
    r = verificar_tamanho_input(texto_medio)
    assert r.allowed is False
    assert r.data["max_tokens"] == 100
