"""Tests for browseAndPlay's ``index`` argument (play the Nth search result).

Behaviour verified:
- default plays the first result (index 1) and stays backward-compatible,
- an explicit index is forwarded to the Node helper as the 4th argv,
- bad / sub-1 index values clamp to 1,
- the index is advertised in the tool schema.
"""

import json
from unittest.mock import Mock, patch

import pytest

from src.jarvis.tools.builtin.browse_and_play import BrowseAndPlayTool, _NODE_SCRIPT


def _ctx():
    cfg = Mock()
    cfg.stream_browser = True
    return Mock(cfg=cfg, user_print=Mock())


def _run(args):
    tool = BrowseAndPlayTool()
    with patch("src.jarvis.tools.builtin.browse_and_play.subprocess.run") as mock_run:
        mock_run.return_value = Mock(
            stdout=json.dumps({"ok": True, "title": "Some Video"}),
            stderr="",
        )
        result = tool.run(args, _ctx())
        return mock_run, result


def _argv(mock_run):
    return list(mock_run.call_args[0][0])


@pytest.mark.unit
def test_schema_exposes_index():
    schema = BrowseAndPlayTool().inputSchema
    assert "index" in schema["properties"]
    assert schema["properties"]["index"]["type"] == "integer"
    assert "query" in schema["required"]
    assert "index" not in schema["required"]  # optional


@pytest.mark.unit
def test_default_index_is_first():
    mock_run, result = _run({"query": "IU Good Day"})
    argv = _argv(mock_run)
    assert argv[:4] == ["node", str(_NODE_SCRIPT), "IU Good Day", "youtube"]
    assert argv[4] == "1"
    assert result.success is True


@pytest.mark.unit
def test_explicit_index_forwarded():
    mock_run, _ = _run({"query": "lofi", "index": 3})
    assert _argv(mock_run)[4] == "3"


@pytest.mark.unit
@pytest.mark.parametrize("bad", [0, -2, "nope", None])
def test_bad_index_clamps_to_one(bad):
    mock_run, _ = _run({"query": "lofi", "index": bad})
    assert _argv(mock_run)[4] == "1"


@pytest.mark.unit
def test_voice_only_mode_does_not_play():
    tool = BrowseAndPlayTool()
    cfg = Mock()
    cfg.stream_browser = False
    ctx = Mock(cfg=cfg, user_print=Mock())
    with patch("src.jarvis.tools.builtin.browse_and_play.subprocess.run") as mock_run:
        result = tool.run({"query": "x", "index": 2}, ctx)
    assert result.success is False
    mock_run.assert_not_called()
