"""Tests para extract_frontmatter, find_headings, estimate_token_count,
smart_split_content y sanitize_for_path."""

import sys
import os

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from core.core import (
    estimate_token_count,
    extract_frontmatter,
    find_headings,
    sanitize_for_path,
    smart_split_content,
)


# ---------------------------------------------------------------------------
# extract_frontmatter
# ---------------------------------------------------------------------------


def test_extract_frontmatter_con_frontmatter():
    content = "---\ntitle: Hello\nauthor: Alice\n---\n# Body\n"
    remaining, data = extract_frontmatter(content)
    assert data is not None
    assert data.get("title") in ("Hello", "Hello")
    assert "# Body" in remaining


def test_extract_frontmatter_sin_frontmatter():
    content = "# Just a heading\n\nSome text."
    remaining, data = extract_frontmatter(content)
    assert data is None
    assert remaining == content


def test_extract_frontmatter_frontmatter_vacio():
    content = "---\n\n---\n# Body\n"
    remaining, data = extract_frontmatter(content)
    # An empty frontmatter block — data may be None or empty dict
    assert "# Body" in remaining


def test_extract_frontmatter_con_listas():
    content = "---\ntags: [go, python, bash]\nauthor: Bob\n---\nContent here\n"
    remaining, data = extract_frontmatter(content)
    assert data is not None
    assert "Content here" in remaining


# ---------------------------------------------------------------------------
# find_headings
# ---------------------------------------------------------------------------


def test_find_headings_normales():
    content = "# Title\n\nSome text\n\n## Section\n\n### Sub\n"
    headings = find_headings(content)
    titles = [h[2] for h in headings]
    levels = [h[3] for h in headings]
    assert titles == ["Title", "Section", "Sub"]
    assert levels == [1, 2, 3]


def test_find_headings_dentro_de_code_blocks():
    content = "# Real\n\n```\n# Not a heading\n```\n\n## Also real\n"
    headings = find_headings(content)
    titles = [h[2] for h in headings]
    assert "Not a heading" not in titles
    assert "Real" in titles
    assert "Also real" in titles


def test_find_headings_escapados():
    content = "# Normal\n\n\\# Escaped heading\n\n## Another\n"
    headings = find_headings(content)
    titles = [h[2] for h in headings]
    # Escaped heading should not appear
    assert "Escaped heading" not in titles
    assert "Normal" in titles


def test_find_headings_en_html_comments():
    content = "# Visible\n\n<!-- # Hidden -->\n\n## Also visible\n"
    headings = find_headings(content)
    titles = [h[2] for h in headings]
    assert "Hidden" not in titles
    assert "Visible" in titles


# ---------------------------------------------------------------------------
# estimate_token_count
# ---------------------------------------------------------------------------


def test_estimate_token_count_texto_vacio():
    assert estimate_token_count("") == 0


def test_estimate_token_count_solo_latin():
    # "hello" = 5 non-whitespace chars * 0.3 = 1 (int)
    result = estimate_token_count("hello")
    assert isinstance(result, int)
    assert result >= 0


def test_estimate_token_count_solo_cjk():
    # 3 CJK chars * 0.7 = 2 (int)
    result = estimate_token_count("\u4e2d\u6587\u8bed")
    assert isinstance(result, int)
    assert result >= 1


def test_estimate_token_count_texto_mixto():
    # Mix of CJK and latin
    result = estimate_token_count("Hello \u4e16\u754c")
    assert isinstance(result, int)
    assert result > 0


# ---------------------------------------------------------------------------
# smart_split_content
# ---------------------------------------------------------------------------


def test_smart_split_content_contenido_corto():
    content = "Short paragraph.\n\nAnother short one."
    parts = smart_split_content(content, max_tokens=1024, max_chars=8000)
    assert len(parts) == 1
    assert parts[0] == content


def test_smart_split_content_contenido_largo():
    # Create content with many small paragraphs that together exceed max_tokens
    paragraphs = ["word " * 10] * 200  # 200 paragraphs of ~10 words each
    content = "\n\n".join(paragraphs)
    parts = smart_split_content(content, max_tokens=50, max_chars=8000)
    assert len(parts) > 1
    for part in parts:
        assert estimate_token_count(part) <= 50 + estimate_token_count("word " * 10)


def test_smart_split_content_parrafo_gigante():
    # Single paragraph that exceeds max_chars — must be force-cut
    long_para = "x" * 20000
    parts = smart_split_content(long_para, max_tokens=1024, max_chars=8000)
    assert len(parts) >= 3  # 20000 / 8000 = at least 3 chunks
    for part in parts:
        assert len(part) <= 8000


# ---------------------------------------------------------------------------
# sanitize_for_path
# ---------------------------------------------------------------------------


def test_sanitize_for_path_texto_normal():
    assert sanitize_for_path("Hello World") == "Hello_World"


def test_sanitize_for_path_caracteres_especiales():
    result = sanitize_for_path("Hello! @World#2024")
    assert "!" not in result
    assert "@" not in result
    assert "#" not in result


def test_sanitize_for_path_texto_muy_largo():
    long_text = "a" * 100
    result = sanitize_for_path(long_text, max_length=50)
    assert len(result) <= 50
    # Should have hash suffix
    assert "_" in result


def test_sanitize_for_path_texto_vacio():
    assert sanitize_for_path("") == "section"


def test_sanitize_for_path_texto_cjk():
    result = sanitize_for_path("\u4e2d\u6587\u6807\u9898")
    assert len(result) > 0
    assert result != "section"
