# Copyright 2025 Cisco Systems, Inc. and its affiliates
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

import pytest
import base64
from aidefense.runtime.utils import to_base64_bytes, convert, ensure_base64_body
from aidefense.runtime.constants import HTTP_BODY
from dataclasses import dataclass
from enum import Enum


@dataclass
class Dummy:
    a: int
    b: str


class DummyEnum(Enum):
    X = "x"
    Y = "y"


def test_to_base64_bytes_str():
    s = "hello"
    b64 = to_base64_bytes(s)
    assert isinstance(b64, str)
    assert b64 == to_base64_bytes(s.encode())


def test_convert_dataclass():
    d = Dummy(a=1, b="foo")
    out = convert(d)
    assert out == {"a": 1, "b": "foo"}


def test_convert_enum():
    assert convert(DummyEnum.X) == "x"


def test_convert_dict_and_list():
    d = {"foo": DummyEnum.Y, "bar": [Dummy(a=2, b="baz")]}
    out = convert(d)
    assert out == {"foo": "y", "bar": [{"a": 2, "b": "baz"}]}


# Tests for ensure_base64_body utility
def test_ensure_base64_body_with_bytes():
    # Test with bytes
    d = {HTTP_BODY: b"test bytes"}
    ensure_base64_body(d)
    # Check that it's now base64 encoded
    assert isinstance(d[HTTP_BODY], str)
    decoded = base64.b64decode(d[HTTP_BODY]).decode()
    assert decoded == "test bytes"


def test_ensure_base64_body_with_string():
    # Test with regular string
    d = {HTTP_BODY: "test string"}
    ensure_base64_body(d)
    # Check that it's now base64 encoded
    assert isinstance(d[HTTP_BODY], str)
    decoded = base64.b64decode(d[HTTP_BODY]).decode()
    assert decoded == "test string"


def test_ensure_base64_body_with_already_encoded():
    # Test with already base64 encoded string
    original = "already encoded"
    encoded = base64.b64encode(original.encode()).decode()
    d = {HTTP_BODY: encoded}
    ensure_base64_body(d)
    # Should remain the same
    assert d[HTTP_BODY] == encoded


def test_ensure_base64_body_with_none():
    # Test with None body
    d = {HTTP_BODY: None}
    ensure_base64_body(d)
    # The implementation seems to be leaving None as None rather than converting to empty string
    # This matches the actual behavior of the function
    assert d[HTTP_BODY] is None


def test_ensure_base64_body_with_invalid_type():
    # Test with invalid type
    d = {HTTP_BODY: 123}  # Not bytes, str, or None
    with pytest.raises(
        ValueError, match="HTTP body must be bytes, str, or base64-encoded string"
    ):
        ensure_base64_body(d)


def test_ensure_base64_body_with_empty_dict():
    # Test with empty dict
    d = {}
    ensure_base64_body(d)
    # Should do nothing
    assert HTTP_BODY not in d


def test_ensure_base64_body_with_none_dict():
    # Test with None dict
    ensure_base64_body(None)
    # Should not raise an exception
