"""Tests for WebRTCPeer — offer/answer, ICE, duplicate offer handling."""

from __future__ import annotations

import asyncio
from unittest.mock import AsyncMock, MagicMock, patch

import pytest


@pytest.fixture
def make_peer():
    from device_agent.webrtc.peer import WebRTCPeer

    def _factory(**kwargs):
        return WebRTCPeer(
            ice_servers=[{"urls": ["stun:stun.l.google.com:19302"]}],
            **kwargs,
        )

    return _factory


@pytest.mark.asyncio
async def test_set_video_track(make_peer):
    peer = make_peer()
    assert peer._video_track is None
    peer.set_video_track("fake_track")
    assert peer._video_track == "fake_track"


@pytest.mark.asyncio
async def test_close_clears_video_track(make_peer):
    peer = make_peer()
    peer.set_video_track("fake_track")

    mock_pc = AsyncMock()
    mock_pc.connectionState = "connected"
    peer._pc = mock_pc

    await peer.close()
    assert peer._pc is None
    assert peer._video_track is None
    assert peer._data_channel_handler is None


@pytest.mark.asyncio
async def test_handle_offer_missing_sdp(make_peer):
    peer = make_peer()
    with pytest.raises(ValueError, match="Offer missing SDP"):
        await peer.handle_offer({})


@pytest.mark.asyncio
async def test_handle_offer_closes_existing_pc(make_peer):
    peer = make_peer()

    old_pc = AsyncMock()
    old_pc.connectionState = "connected"
    peer._pc = old_pc
    peer._video_track = "old_track"

    fake_sdp = (
        "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n"
        "m=video 9 UDP/TLS/RTP/SAVPF 96\r\nc=IN IP4 0.0.0.0\r\n"
        "a=rtcp-mux\r\na=rtpmap:96 H264/90000\r\n"
    )

    with patch("device_agent.webrtc.peer.RTCPeerConnection") as MockPC:
        mock_pc = AsyncMock()
        mock_pc.connectionState = "new"
        mock_pc.localDescription = MagicMock()
        mock_pc.localDescription.sdp = "fake_answer_sdp"
        MockPC.return_value = mock_pc

        prepare = AsyncMock(return_value="new_track")
        peer._on_prepare_track = prepare
        peer._video_track = None

        answer = await peer.handle_offer({"sdp": fake_sdp})

    old_pc.close.assert_awaited_once()
    assert answer["type"] == "answer"
    assert answer["sdp"] == "fake_answer_sdp"


@pytest.mark.asyncio
async def test_handle_ice_candidate_no_pc(make_peer):
    peer = make_peer()
    await peer.handle_ice_candidate({"candidate": "candidate:1 1 UDP 2130706431 192.168.1.1 50000 typ host"})


@pytest.mark.asyncio
async def test_connected_property(make_peer):
    peer = make_peer()
    assert not peer.connected

    mock_pc = MagicMock()
    mock_pc.connectionState = "connected"
    peer._pc = mock_pc
    assert peer.connected

    mock_pc.connectionState = "disconnected"
    assert not peer.connected
