"""Tests for VDO.Ninja client URL parsing, encryption, and integration."""

import pytest
import sys
import os

# Add src to path for imports
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))


# ── URL parsing tests ─────────────────────────────────────────────────

class TestParseVDONinjaURL:
    def test_basic_view_url(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?view=eWWbtku")
        assert result["stream_id"] == "eWWbtku"

    def test_view_with_codec(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?view=abc123&codec=vp8")
        assert result["stream_id"] == "abc123"
        assert result["codec"] == "vp8"

    def test_view_with_password(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?view=abc123&password=mypass")
        assert result["stream_id"] == "abc123"
        assert result["password"] == "mypass"

    def test_password_false(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?view=abc123&password=false")
        assert result["password"] is False

    def test_no_scheme(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("vdo.ninja/?view=test123")
        assert result["stream_id"] == "test123"

    def test_empty_url(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("")
        assert result == {}

    def test_custom_wss(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?view=test&wss=wss://my.server:443")
        assert result["server"] == "wss://my.server:443"

    def test_room_param(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?view=test&room=myroom")
        assert result["room"] == "myroom"

    def test_v_shorthand(self):
        from djhud.vdoninja_client import parse_vdoninja_url
        result = parse_vdoninja_url("https://vdo.ninja/?v=shortid")
        assert result["stream_id"] == "shortid"


class TestIsVDONinjaURL:
    def test_standard_url(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("https://vdo.ninja/?view=abc") is True

    def test_no_scheme(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("vdo.ninja/?view=abc") is True

    def test_backup_domain(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("https://backup.vdo.ninja/?view=abc") is True

    def test_rtc_ninja(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("https://rtc.ninja/?view=abc") is True

    def test_djhud_ws_url(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("ws://10.66.66.3:7088/ws") is False

    def test_djhud_http_url(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("http://10.66.66.3:7088/viewer") is False

    def test_bare_ip(self):
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("10.66.66.3:7088") is False

    def test_view_param_generic(self):
        """A URL with ?view= that is NOT on a vdo.ninja domain is still
        detected as VDO.Ninja since the user likely means a VDO.Ninja stream."""
        from djhud.vdoninja_client import is_vdoninja_url
        assert is_vdoninja_url("https://myserver.com/?view=abc") is True


# ── Encryption tests ──────────────────────────────────────────────────

class TestEncryption:
    def test_generate_hash_deterministic(self):
        from djhud.vdoninja_client import _generate_hash
        h1 = _generate_hash("someEncryptionKey123", "vdo.ninja")
        h2 = _generate_hash("someEncryptionKey123", "vdo.ninja")
        assert h1 == h2
        assert len(h1) == 6

    def test_generate_hash_matches_sdk(self):
        """Verify our hash matches the VDO.Ninja SDK output."""
        from djhud.vdoninja_client import _generate_hash
        # SDK: SHA256("someEncryptionKey123" + "vdo.ninja")[:6] = "808d64"
        h = _generate_hash("someEncryptionKey123", "vdo.ninja")
        assert h == "808d64", f"Expected '808d64', got '{h}'"

    def test_generate_hash_different_passwords(self):
        from djhud.vdoninja_client import _generate_hash
        h1 = _generate_hash("pass1", "vdo.ninja")
        h2 = _generate_hash("pass2", "vdo.ninja")
        assert h1 != h2

    def test_generate_hash_same_password_same_hash_regardless_of_stream(self):
        """The hash depends only on password+salt, not on the stream ID."""
        from djhud.vdoninja_client import _generate_hash
        h = _generate_hash("someEncryptionKey123", "vdo.ninja")
        # Same hash for any stream ID — stream ID is just prepended, not hashed
        assert h == "808d64"

    def test_encrypt_decrypt_roundtrip(self):
        from djhud.vdoninja_client import _encrypt_message, _decrypt_message, _CRYPTO_OK
        if not _CRYPTO_OK:
            pytest.skip("cryptography not installed")
        plaintext = '{"type":"offer","sdp":"v=0..."}'
        password = "someEncryptionKey123vdo.ninja"
        ct, iv = _encrypt_message(plaintext, password)
        assert ct != plaintext
        assert len(iv) == 32  # 16 bytes = 32 hex chars
        # Verify output is hex-encoded (not base64)
        assert all(c in '0123456789abcdef' for c in ct)
        assert all(c in '0123456789abcdef' for c in iv)
        decrypted = _decrypt_message(ct, iv, password)
        assert decrypted == plaintext

    def test_encrypt_produces_different_output_each_time(self):
        """Due to random IV, same plaintext encrypts differently each time."""
        from djhud.vdoninja_client import _encrypt_message, _CRYPTO_OK
        if not _CRYPTO_OK:
            pytest.skip("cryptography not installed")
        ct1, _ = _encrypt_message("hello", "key")
        ct2, _ = _encrypt_message("hello", "key")
        # Different IVs → different ciphertexts (with overwhelming probability)
        assert ct1 != ct2


# ── Integration with app.py dispatch ──────────────────────────────────

class TestStreamDispatch:
    """Test that _capture_source_stream correctly routes to the right client type."""

    def test_normalize_stream_key_vdoninja(self):
        """VDO.Ninja URLs use the raw URL as key."""
        # We can't import app.py directly (needs tkinter), but we can test
        # the is_vdoninja_url function which drives the routing
        from djhud.vdoninja_client import is_vdoninja_url
        url = "https://vdo.ninja/?view=test123"
        assert is_vdoninja_url(url) is True

    def test_normalize_stream_key_djhud(self):
        """DJ HUD URLs use normalized ws:// URL as key."""
        from djhud.vdoninja_client import is_vdoninja_url
        from djhud.stream_client import normalize_stream_url
        url = "http://10.66.66.3:7088/viewer"
        assert is_vdoninja_url(url) is False
        assert normalize_stream_url(url) == "ws://10.66.66.3:7088/ws"


# ── Client construction tests ─────────────────────────────────────────

class TestVDONinjaClientInit:
    def test_missing_aiortc_raises(self):
        """If aiortc is not installed, constructor should raise ImportError."""
        import djhud.vdoninja_client as mod
        if not mod._AIORTC_OK:
            with pytest.raises(ImportError, match="aiortc"):
                mod.VDONinjaClient("https://vdo.ninja/?view=test")

    def test_missing_stream_id_raises(self):
        import djhud.vdoninja_client as mod
        if not mod._AIORTC_OK:
            pytest.skip("aiortc not installed")
        with pytest.raises(ValueError, match="stream ID"):
            mod.VDONinjaClient("https://vdo.ninja/")

    def test_default_password(self):
        import djhud.vdoninja_client as mod
        if not mod._AIORTC_OK:
            pytest.skip("aiortc not installed")
        client = mod.VDONinjaClient("https://vdo.ninja/?view=test")
        assert client._password == "someEncryptionKey123"
        assert client._hashcode != ""
        assert len(client._hashcode) == 6

    def test_password_false(self):
        import djhud.vdoninja_client as mod
        if not mod._AIORTC_OK:
            pytest.skip("aiortc not installed")
        client = mod.VDONinjaClient("https://vdo.ninja/?view=test&password=false")
        assert client._password is None
        assert client._hashcode == ""


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
