from unittest.mock import patch, MagicMock
from src.markdown_helper import MarkdownRenderer

def _mock_table(mock_imgui):
 mock_imgui.TableFlags_ = type("T", (), {"borders": 1, "row_bg": 2, "resizable": 4})()
 mock_imgui.TableColumnFlags_ = type("C", (), {"width_stretch": 8})()
 mock_imgui.begin_table.return_value = True
 mock_imgui.table_next_column = lambda: None
 mock_imgui.table_next_row = lambda: None
 mock_imgui.table_headers_row = lambda: None
 mock_imgui.text = lambda *a, **k: None
 mock_imgui.text_wrapped = lambda *a, **k: None
 mock_imgui.end_table = lambda: None
 mock_imgui.same_line = lambda: None
 mock_imgui.spacing = lambda: None
 mock_imgui.indent = lambda *a: None
 mock_imgui.unindent = lambda *a: None

def test_render_calls_imgui_md_render_for_bullet_chunks():
 md = "- one\n- two\n- three\n"
 with patch("src.markdown_helper.imgui_md") as mock_md, \
      patch("src.markdown_helper.imgui") as mock_imgui, \
      patch("src.markdown_table.imgui") as mock_table_imgui:
  _mock_table(mock_table_imgui)
  mock_md.render = MagicMock()
  mock_imgui.spacing = MagicMock()
  MarkdownRenderer().render(md, context_id="bullets")
  assert mock_md.render.call_count == 1, f"expected 1 imgui_md.render call (full chunk passed through), got {mock_md.render.call_count}"
  assert mock_imgui.spacing.call_count >= 1, "imgui.spacing must be called to force vertical gap between chunks"

def test_render_does_not_strip_bullet_prefix_from_markdown():
 md = "- one\n- two\n"
 with patch("src.markdown_helper.imgui_md") as mock_md, \
      patch("src.markdown_helper.imgui") as mock_imgui, \
      patch("src.markdown_table.imgui") as mock_table_imgui:
  _mock_table(mock_table_imgui)
  mock_md.render = MagicMock()
  mock_imgui.spacing = MagicMock()
  MarkdownRenderer().render(md, context_id="bullets")
  args, _ = mock_md.render.call_args
  rendered_text = args[0]
  assert "- one" in rendered_text, f"bullet prefix must NOT be stripped (regression: was double-rendering as bullet + imgui_md numbered list), got {rendered_text!r}"
  assert "- two" in rendered_text

def test_render_passes_numbered_list_intact_to_imgui_md():
 md = "1. First question\n2. Second question\n"
 with patch("src.markdown_helper.imgui_md") as mock_md, \
      patch("src.markdown_helper.imgui") as mock_imgui, \
      patch("src.markdown_table.imgui") as mock_table_imgui:
  _mock_table(mock_table_imgui)
  mock_md.render = MagicMock()
  mock_imgui.spacing = MagicMock()
  MarkdownRenderer().render(md, context_id="numbered")
  assert mock_md.render.call_count == 1
  args, _ = mock_md.render.call_args
  rendered_text = args[0]
  assert "1. First question" in rendered_text
  assert "2. Second question" in rendered_text
  assert not mock_imgui.bullet.called, "no manual imgui.bullet should be added — let imgui_md handle list rendering"

def test_normalize_nested_list_endings_inserts_blank_after_nested_item():
 r = MarkdownRenderer()
 text = "- top\n  - nested last\nnext paragraph\n"
 out = r._normalize_nested_list_endings(text)
 assert "  - nested last\n\nnext paragraph" in out, f"expected blank line between nested list item and less-indented next line, got {out!r}"

def test_normalize_nested_list_endings_does_not_insert_blank_for_top_level_list():
 r = MarkdownRenderer()
 text = "- one\n- two\n- three\nnext paragraph\n"
 out = r._normalize_nested_list_endings(text)
 assert out == text, f"top-level list ending should not trigger blank line insertion, got {out!r}"

def test_normalize_nested_list_endings_does_not_double_blank():
 r = MarkdownRenderer()
 text = "- a\n  - b\n\nalready blank\n"
 out = r._normalize_nested_list_endings(text)
 assert out == text, f"already-blank separator should not get doubled, got {out!r}"

def test_normalize_bullet_delimiters_still_converts_asterisk():
 r = MarkdownRenderer()
 text = "- one\n* two\n+ three\n"
 out = r._normalize_bullet_delimiters(text)
 assert "- one" in out
 assert "- two" in out and "* two" not in out, f"* must be converted to -, got {out!r}"
 assert "+ three" in out, f"+ must be left alone, got {out!r}"
 assert "+ three" in out, f"+ must be left alone, got {out!r}"

def test_normalize_list_continuations_strips_blank_between_bullet_and_indented_continuation():
 r = MarkdownRenderer()
 text = "- bullet text\n\n   continuation paragraph\n\nnext paragraph\n"
 out = r._normalize_list_continuations(text)
 assert "   continuation paragraph" in out
 assert "- bullet text\n   continuation paragraph" in out, f"blank between bullet and indented continuation must be stripped (workaround for imgui_md BLOCK_P no-NewLine-inside-list bug), got {out!r}"
 assert "next paragraph" in out

def test_normalize_list_continuations_preserves_blank_between_indented_and_next_paragraph():
 r = MarkdownRenderer()
 text = "- bullet\n   cont\n\nnext\n"
 out = r._normalize_list_continuations(text)
 assert "- bullet\n   cont\n\nnext\n" == out, f"blank between continuation and next paragraph must be preserved (it ends the list item), got {out!r}"

def test_normalize_list_continuations_leaves_simple_list_alone():
 r = MarkdownRenderer()
 text = "- one\n- two\n- three\n"
 out = r._normalize_list_continuations(text)
 assert out == text, f"simple list with no continuations should be unchanged, got {out!r}"
