"""Tests for PoseSoundBridge.send_finger and send_pinch."""
from __future__ import annotations

from unittest.mock import MagicMock

from data_only_viz.finger_strike import StrikeEvent
from data_only_viz.pose_bridge import PoseSoundBridge


def _bridge() -> PoseSoundBridge:
    b = PoseSoundBridge()
    b._client = MagicMock()      # stub the UDP client
    return b


def test_send_finger_emits_expected_osc():
    b = _bridge()
    ev = StrikeEvent(hand=1, finger=2, strike_speed=0.5, z=0.1,
                     tipx=0.7, tipy=0.6)
    b.send_finger(ev)
    b._client.send_message.assert_called_once()
    addr, args = b._client.send_message.call_args[0]
    assert addr == "/pose/finger"
    assert args[0] == 0           # pid
    assert args[1] == 1           # hand
    assert args[2] == 2           # finger
    assert abs(args[3] - 0.5) < 1e-6
    assert len(args) == 7
    # Verify z, tipx, tipy values
    assert abs(args[4] - 0.1) < 1e-6     # z
    assert abs(args[5] - 0.7) < 1e-6     # tipx
    assert abs(args[6] - 0.6) < 1e-6     # tipy
    # types matter for OSC tags / the SC ~fpResolve reader
    assert isinstance(args[0], int) and not isinstance(args[0], bool)
    assert isinstance(args[1], int) and isinstance(args[2], int)
    assert all(isinstance(a, float) for a in args[3:7])


def test_send_pinch_emits_state_as_4th_arg():
    """send_pinch must put the edge state (1=engage, 0=release) as 4th arg."""
    b = _bridge()

    class _FakePinchEvent:
        hand = 0
        finger = 1
        state = 1

    b.send_pinch(_FakePinchEvent())
    b._client.send_message.assert_called_once()
    addr, args = b._client.send_message.call_args[0]
    assert addr == "/pose/pinch"
    assert args[0] == 0          # pid
    assert args[1] == 0          # hand
    assert args[2] == 1          # finger
    assert args[3] == 1          # state (engage edge)
    assert len(args) == 4


def test_send_pinch_release_state_is_zero():
    """Release edge: state=0 appears as 4th arg."""
    b = _bridge()

    class _FakeRelease:
        hand = 1
        finger = 2
        state = 0

    b.send_pinch(_FakeRelease())
    addr, args = b._client.send_message.call_args[0]
    assert addr == "/pose/pinch"
    assert args[3] == 0          # state = release
