"""Tests for the text/URL QR code generation node."""

import pytest

from fw_nodes_qrcode.nodes.generate import QRCodeGenerateNode


@pytest.fixture
def node():
    return QRCodeGenerateNode()


async def test_generate_basic(node, mock_context):
    result = await node.execute({"text": "https://example.com"}, mock_context)

    assert result.size_bytes > 0
    assert result.version >= 1
    assert result.image["content_type"] == "image/png"
    assert result.image["filename"] == "qrcode.png"


async def test_generate_stores_valid_png(node, mock_context):
    await node.execute({"text": "hello"}, mock_context)

    assert len(mock_context._stored_binaries) == 1
    png_data = mock_context._stored_binaries[0]["data"]
    assert png_data[:8] == b"\x89PNG\r\n\x1a\n"


async def test_generate_custom_colors(node, mock_context):
    result = await node.execute(
        {"text": "test", "fill_color": "#FF0000", "back_color": "#00FF00"},
        mock_context,
    )
    assert result.size_bytes > 0


async def test_generate_custom_size(node, mock_context):
    small = await node.execute({"text": "test", "size": 2, "border": 1}, mock_context)
    large = await node.execute({"text": "test", "size": 20, "border": 4}, mock_context)
    assert small.size_bytes < large.size_bytes


async def test_generate_error_correction_levels(node, mock_context):
    for level in ["L", "M", "Q", "H"]:
        result = await node.execute(
            {"text": "error correction test", "error_correction": level},
            mock_context,
        )
        assert result.version >= 1


async def test_generate_long_text(node, mock_context):
    result = await node.execute({"text": "A" * 500}, mock_context)
    assert result.version > 1


@pytest.mark.parametrize("style", ["square", "gapped_square", "circle", "rounded", "vertical_bars", "horizontal_bars"])
async def test_module_styles(node, mock_context, style):
    result = await node.execute({"text": "style test", "module_style": style}, mock_context)
    assert result.size_bytes > 0


@pytest.mark.parametrize(
    "mode", ["solid", "radial_gradient", "square_gradient", "horizontal_gradient", "vertical_gradient"]
)
async def test_color_modes(node, mock_context, mode):
    result = await node.execute(
        {"text": "gradient test", "color_mode": mode, "fill_color": "#000000", "gradient_end_color": "#0000FF"},
        mock_context,
    )
    assert result.size_bytes > 0


async def test_combined_styling(node, mock_context):
    result = await node.execute(
        {
            "text": "https://example.com",
            "color_mode": "radial_gradient",
            "fill_color": "#FF0000",
            "gradient_end_color": "#00FF00",
            "module_style": "circle",
        },
        mock_context,
    )
    assert result.size_bytes > 0


async def test_schema_field_order(node):
    """Format fields should appear before style fields in the JSON schema."""
    schema = node.input_schema.model_json_schema()
    keys = list(schema["properties"].keys())
    text_idx = keys.index("text")
    size_idx = keys.index("size")
    assert text_idx < size_idx, f"'text' (format) should appear before 'size' (style), got order: {keys}"
