import numpy as np
import pytest
from tests.node_tests._shared import make_field
from backend.nodes.helpers import mask_to_bool


def test_grain_mark_height():
    from backend.nodes.grain_mark import GrainMark

    node = GrainMark()
    data = np.zeros((64, 64))
    data[20:40, 20:40] = 1.0  # raised region
    field = make_field(data=data)
    mask, = node.process(field, "height", 0.5, 1.0, 10, False)
    binary = mask_to_bool(mask)
    assert binary[30, 30]  # center of raised region should be marked
    assert not binary[0, 0]  # corner should not be marked


def test_grain_mark_slope():
    from backend.nodes.grain_mark import GrainMark

    node = GrainMark()
    field = make_field(shape=(64, 64))
    mask, = node.process(field, "slope", 0.3, 1.0, 5, False)
    assert mask.shape == (64, 64)
    assert mask.dtype == np.uint8


def test_grain_mark_inverted():
    from backend.nodes.grain_mark import GrainMark

    node = GrainMark()
    data = np.zeros((32, 32))
    data[10:20, 10:20] = 1.0
    field = make_field(data=data)
    mask_normal, = node.process(field, "height", 0.5, 1.0, 1, False)
    mask_inv, = node.process(field, "height", 0.5, 1.0, 1, True)
    # Inverted should be complement (approximately)
    n1 = mask_to_bool(mask_normal).sum()
    n2 = mask_to_bool(mask_inv).sum()
    assert n1 + n2 > 0


def test_grain_mark_min_size():
    from backend.nodes.grain_mark import GrainMark

    node = GrainMark()
    data = np.zeros((64, 64))
    data[30, 30] = 1.0  # single pixel
    data[10:20, 10:20] = 1.0  # larger region
    field = make_field(data=data)
    mask, = node.process(field, "height", 0.5, 1.0, 50, False)
    binary = mask_to_bool(mask)
    # Single pixel should be filtered out
    assert not binary[30, 30]
