"""Tests for ExcelRenderer — Markdown/JSON → .xlsx mapping (U3)."""

from __future__ import annotations

import json
from pathlib import Path

from openpyxl import load_workbook

from agentkit.documents.renderers.excel_renderer import ExcelRenderer


def _render(content: str, tmp_path: Path) -> Path:
    out = tmp_path / "test.xlsx"
    ExcelRenderer().render(content, out)
    return out


def _read_workbook(path: Path) -> dict[str, list[list[str]]]:
    """Return {sheet_name: [[row cells], ...]} from a .xlsx file."""
    wb = load_workbook(str(path))
    result: dict[str, list[list[str]]] = {}
    for ws in wb.worksheets:
        rows: list[list[str]] = []
        for row in ws.iter_rows(values_only=True):
            rows.append([str(c) if c is not None else "" for c in row])
        result[ws.title] = rows
    return result


def test_markdown_single_table(tmp_path: Path) -> None:
    """A single GFM table becomes a Table1 sheet with correct data."""
    md = "| Name | Age |\n| --- | --- |\n| Alice | 30 |\n| Bob | 25 |\n"
    path = _render(md, tmp_path)
    sheets = _read_workbook(path)
    assert "Table1" in sheets
    rows = sheets["Table1"]
    assert rows[0] == ["Name", "Age"]
    assert rows[1] == ["Alice", "30"]
    assert rows[2] == ["Bob", "25"]


def test_markdown_multiple_tables(tmp_path: Path) -> None:
    """Multiple GFM tables become separate sheets (Table1, Table2)."""
    md = (
        "| A | B |\n| --- | --- |\n| 1 | 2 |\n\n"
        "Some text between.\n\n"
        "| C | D |\n| --- | --- |\n| 3 | 4 |\n"
    )
    path = _render(md, tmp_path)
    sheets = _read_workbook(path)
    assert "Table1" in sheets
    assert "Table2" in sheets
    assert sheets["Table1"][0] == ["A", "B"]
    assert sheets["Table2"][0] == ["C", "D"]


def test_markdown_no_table_creates_summary(tmp_path: Path) -> None:
    """Markdown without tables puts text lines in a Summary sheet."""
    md = "Just some text.\nAnother line.\n"
    path = _render(md, tmp_path)
    sheets = _read_workbook(path)
    # At least one sheet exists with the text
    all_text = []
    for rows in sheets.values():
        all_text.extend(cell for row in rows for cell in row)
    assert "Just some text." in all_text
    assert "Another line." in all_text


def test_json_input_multi_sheet(tmp_path: Path) -> None:
    """JSON input {sheet: rows} creates named sheets."""
    data = {
        "Sales": [["Product", "Revenue"], ["Widget", "1000"], ["Gadget", "2000"]],
        "Costs": [["Item", "Amount"], ["Rent", "500"]],
    }
    path = _render(json.dumps(data), tmp_path)
    sheets = _read_workbook(path)
    assert "Sales" in sheets
    assert "Costs" in sheets
    assert sheets["Sales"][0] == ["Product", "Revenue"]
    assert sheets["Sales"][1] == ["Widget", "1000"]
    assert sheets["Costs"][1] == ["Rent", "500"]


def test_json_input_single_sheet(tmp_path: Path) -> None:
    """JSON with one sheet creates exactly that sheet."""
    data = {"Data": [["X", "Y"], ["1", "2"]]}
    path = _render(json.dumps(data), tmp_path)
    sheets = _read_workbook(path)
    assert "Data" in sheets
    assert sheets["Data"][0] == ["X", "Y"]


def test_empty_markdown(tmp_path: Path) -> None:
    """Empty input produces a valid workbook with at least one sheet."""
    path = _render("", tmp_path)
    assert path.exists()
    wb = load_workbook(str(path))
    assert len(wb.sheetnames) >= 1


def test_mixed_table_and_text(tmp_path: Path) -> None:
    """Text before/after a table goes to Summary, table goes to Table1."""
    md = "Intro line.\n\n| Col1 | Col2 |\n| --- | --- |\n| a | b |\n\nOutro line.\n"
    path = _render(md, tmp_path)
    sheets = _read_workbook(path)
    assert "Table1" in sheets
    # Summary should contain intro and outro
    if "Summary" in sheets:
        summary_cells = [cell for row in sheets["Summary"] for cell in row]
        assert "Intro line." in summary_cells
        assert "Outro line." in summary_cells


def test_long_sheet_name_truncated(tmp_path: Path) -> None:
    """Sheet names longer than 31 chars are truncated (Excel limit)."""
    long_name = "A" * 50
    data = {long_name: [["x"]]}
    path = _render(json.dumps(data), tmp_path)
    wb = load_workbook(str(path))
    # The sheet name should be at most 31 chars
    for name in wb.sheetnames:
        assert len(name) <= 31
