"""Tests for pybyd._crypto.bangcle (BangcleCodec).

Test vectors cross-validated against the Node.js bangcle.js implementation.
"""

from __future__ import annotations

import pytest

from pybyd._crypto.bangcle import BangcleCodec
from pybyd.exceptions import BangcleError


class TestBangcleRoundtrip:
    def test_simple_string(self, codec: BangcleCodec) -> None:
        plaintext = "hello bangcle test"
        encoded = codec.encode_envelope(plaintext)
        assert encoded.startswith("F")
        decoded = codec.decode_envelope(encoded)
        assert decoded == plaintext.encode("utf-8")

    def test_json_payload(self, codec: BangcleCodec) -> None:
        payload = '{"encryData":"ABCDEF","sign":"123456"}'
        encoded = codec.encode_envelope(payload)
        decoded = codec.decode_envelope(encoded)
        assert decoded.decode("utf-8") == payload

    def test_large_payload(self, codec: BangcleCodec) -> None:
        large = "x" * 4096
        encoded = codec.encode_envelope(large)
        decoded = codec.decode_envelope(encoded)
        assert decoded.decode("utf-8") == large

    def test_bytes_input(self, codec: BangcleCodec) -> None:
        data = b"\x00\x01\x02\xff" * 10
        encoded = codec.encode_envelope(data)
        decoded = codec.decode_envelope(encoded)
        assert decoded == data

    def test_exact_block_boundary(self, codec: BangcleCodec) -> None:
        """16-byte input should roundtrip (PKCS7 adds a full block)."""
        plaintext = "a" * 16
        encoded = codec.encode_envelope(plaintext)
        decoded = codec.decode_envelope(encoded)
        assert decoded == plaintext.encode("utf-8")

    def test_one_byte(self, codec: BangcleCodec) -> None:
        encoded = codec.encode_envelope("x")
        decoded = codec.decode_envelope(encoded)
        assert decoded == b"x"


class TestBangcleCrossValidation:
    """Verify against known outputs from the JS implementation."""

    def test_encode_matches_js(self, codec: BangcleCodec) -> None:
        encoded = codec.encode_envelope("hello bangcle test")
        assert encoded == "F69fo87a35gvF8IFaJGOb0AB64edzoiIXsB03txGnKw4="

    def test_decode_js_encoded(self, codec: BangcleCodec) -> None:
        decoded = codec.decode_envelope("F69fo87a35gvF8IFaJGOb0AB64edzoiIXsB03txGnKw4=")
        assert decoded == b"hello bangcle test"

    def test_json_encode_matches_js(self, codec: BangcleCodec) -> None:
        payload = '{"encryData":"ABCDEF","sign":"123456"}'
        encoded = codec.encode_envelope(payload)
        assert encoded == "Fl2q53GlBNETSquEkkS27ukcvLmXLJr078YLr/2FjlnwUceoEt4JxDV2UffiheJZj"

    def test_json_decode_js_encoded(self, codec: BangcleCodec) -> None:
        decoded = codec.decode_envelope("Fl2q53GlBNETSquEkkS27ukcvLmXLJr078YLr/2FjlnwUceoEt4JxDV2UffiheJZj")
        assert decoded == b'{"encryData":"ABCDEF","sign":"123456"}'


class TestBangcleErrors:
    def test_missing_f_prefix(self, codec: BangcleCodec) -> None:
        with pytest.raises(BangcleError, match="must start with"):
            codec.decode_envelope("notFprefixed")

    def test_empty_input(self, codec: BangcleCodec) -> None:
        with pytest.raises(BangcleError):
            codec.decode_envelope("")

    def test_invalid_base64(self, codec: BangcleCodec) -> None:
        with pytest.raises(BangcleError):
            codec.decode_envelope("F!!!invalid!!!")
