from __future__ import annotations

import pytest

import xy.pyplot as plt


def teardown_function():
    plt.close("all")


def test_line_cap_mutations_fail_loudly_and_gapcolor_round_trips():
    _, ax = plt.subplots()
    line = ax.plot([0, 1], [0, 1], dashes=[4, 4])[0]

    with pytest.raises(NotImplementedError):
        line.set_dash_capstyle("butt")
    with pytest.raises(NotImplementedError):
        line.set_solid_capstyle("round")
    line.set_gapcolor("red")
    assert line.get_gapcolor() == "red"
    line.set_gapcolor(None)
    assert line.get_gapcolor() is None


def test_dashed_gapcolor_materializes_behind_one_named_foreground_trace() -> None:
    _, ax = plt.subplots()
    line = ax.plot(
        [0, 1, 2],
        [0, 1, 0],
        dashes=[4, 4],
        gapcolor="tab:pink",
        color="tab:blue",
        label="alternating",
    )[0]

    assert line.get_gapcolor() == "#e377c2"
    spec, _blob = ax._build_chart(640, 480).figure().build_payload()
    assert [
        (trace["name"], trace["style"]["color"], trace["style"].get("dash"))
        for trace in spec["traces"]
    ] == [
        (None, "#e377c2", None),
        ("alternating", "#1f77b4", [8.3333, 8.3333]),
    ]


def test_text_preserves_visible_font_alignment_and_rotation_style():
    _, ax = plt.subplots()
    text = ax.text(
        0.2,
        0.3,
        "styled",
        ha="center",
        va="top",
        fontweight="bold",
        fontfamily="serif",
        rotation=45,
        fontsize=12,
    )

    assert text._entry["kwargs"]["anchor"] == "middle"
    assert text._entry["kwargs"]["style"] == {
        "font_size": 12.0,
        "vertical_align": "top",
        "font_weight": "bold",
        "font_family": "serif",
        "rotation": 45.0,
    }


def test_annotate_preserves_arrow_bbox_alignment_rotation_and_font_style():
    _, ax = plt.subplots()
    note = ax.annotate(
        "note",
        (1, 2),
        xytext=(5, 6),
        arrowprops={"arrowstyle": "->", "color": "red"},
        bbox={"boxstyle": "round", "facecolor": "white"},
        ha="right",
        va="bottom",
        family="monospace",
        weight="bold",
        rotation=30,
        fontsize=9,
    )

    kwargs = note._entry["kwargs"]
    assert kwargs["arrowprops"] == {"arrowstyle": "->", "color": "red"}
    assert kwargs["bbox"] == {"boxstyle": "round", "facecolor": "white"}
    assert kwargs["anchor"] == "end"
    # matplotlib semantics: the text sits AT xytext (data coords), and the
    # arrowprops materialize an @arrow entry pointing back at xy.
    assert note._entry["args"][:2] == (5.0, 6.0)
    arrow = next(e for e in ax._entries if e["kind"] == "@arrow")
    assert arrow["args"] == (5.0, 6.0, 1.0, 2.0)
    assert arrow["kwargs"]["color"] == "red"
    assert kwargs["style"] == {
        "font_size": 9.0,
        "vertical_align": "bottom",
        "font_weight": "bold",
        "font_family": "monospace",
        "rotation": 30.0,
    }


def test_bar_align_edge_uses_edge_geometry_instead_of_center_approximation():
    _, ax = plt.subplots()
    bars = ax.bar([1, 3], [2, 4], width=0.5, align="edge")

    assert list(bars._entry["x"]) == [1.25, 3.25]
    assert bars._entry["kwargs"]["width"] == 0.5
    with pytest.raises(ValueError):
        ax.bar(["a"], [1], align="edge")
