"""Contains all unit tests for the protect_wheel_wrapper function."""

from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest
import requests

from voraus_pipeline_utils.methods.protect import protect_wheel_wrapper


@patch("voraus_pipeline_utils.methods.protect.requests.post")
def test_protect_wheel_wrapper_success_replace(post_request_mock: MagicMock, tmp_path: Path) -> None:
    # Create a dummy wheel file
    wheel_file = tmp_path / "test_wheel.whl"
    wheel_file.write_bytes(b"dummy wheel content")

    # Mock the response
    mock_response = MagicMock()
    mock_response.content = b"encrypted wheel content"
    post_request_mock.return_value = mock_response

    # Call the function
    protect_wheel_wrapper(
        wheel_file=wheel_file,
        identifier="test-package-1",
        api_endpoint="https://protector.example.com",
        access_key_id="test_key",
        access_secret_key="test_secret",  # noqa: S106
        replace=True,
    )

    # Verify the request was made correctly
    post_request_mock.assert_called_once()
    call_args = post_request_mock.call_args
    assert call_args.args[0] == "https://protector.example.com/encrypt/python"
    assert call_args.kwargs["params"] == {"identifier": "test-package-1"}
    assert call_args.kwargs["headers"] == {"access_key_id": "test_key", "access_secret_key": "test_secret"}
    expected_timeout = 60
    assert call_args.kwargs["timeout"] == expected_timeout
    assert "files" in call_args.kwargs

    # Verify the file was replaced
    assert wheel_file.exists()
    assert wheel_file.read_bytes() == b"encrypted wheel content"


@patch("voraus_pipeline_utils.methods.protect.requests.post")
def test_protect_wheel_wrapper_success_no_replace(post_request_mock: MagicMock, tmp_path: Path) -> None:
    # Create a dummy wheel file
    wheel_file = tmp_path / "test_wheel.whl"
    original_content = b"dummy wheel content"
    wheel_file.write_bytes(original_content)

    # Mock the response
    mock_response = MagicMock()
    mock_response.content = b"encrypted wheel content"
    post_request_mock.return_value = mock_response

    # Call the function
    protect_wheel_wrapper(
        wheel_file=wheel_file,
        identifier="test-package-1",
        api_endpoint="https://protector.example.com",
        access_key_id="test_key",
        access_secret_key="test_secret",  # noqa: S106
        replace=False,
    )

    # Verify the request was made correctly
    post_request_mock.assert_called_once()

    # Verify the original file was NOT replaced
    assert wheel_file.exists()
    assert wheel_file.read_bytes() == original_content

    # Verify a new encrypted file was created
    encrypted_file = tmp_path / "test_wheel_encrypted.whl"
    assert encrypted_file.exists()
    assert encrypted_file.read_bytes() == b"encrypted wheel content"


@patch("voraus_pipeline_utils.methods.protect.requests.post")
def test_protect_wheel_wrapper_strips_trailing_slash(post_request_mock: MagicMock, tmp_path: Path) -> None:
    # Create a dummy wheel file
    wheel_file = tmp_path / "test_wheel.whl"
    wheel_file.write_bytes(b"dummy wheel content")

    # Mock the response
    mock_response = MagicMock()
    mock_response.content = b"encrypted wheel content"
    post_request_mock.return_value = mock_response

    # Call the function with trailing slash in endpoint
    protect_wheel_wrapper(
        wheel_file=wheel_file,
        identifier="test-package-1",
        api_endpoint="https://protector.example.com/",
        access_key_id="test_key",
        access_secret_key="test_secret",  # noqa: S106
        replace=True,
    )

    # Verify the URL was constructed correctly without double slashes
    call_args = post_request_mock.call_args
    assert call_args.args[0] == "https://protector.example.com/encrypt/python"


@patch("voraus_pipeline_utils.methods.protect.requests.post")
def test_protect_wheel_wrapper_request_failure(post_request_mock: MagicMock, tmp_path: Path) -> None:
    # Create a dummy wheel file
    wheel_file = tmp_path / "test_wheel.whl"
    wheel_file.write_bytes(b"dummy wheel content")

    # Mock the response to raise an HTTP error
    mock_response = MagicMock()
    mock_response.raise_for_status.side_effect = requests.HTTPError("API Error")
    post_request_mock.return_value = mock_response

    # Call the function and expect an exception
    with pytest.raises(requests.HTTPError, match="API Error"):
        protect_wheel_wrapper(
            wheel_file=wheel_file,
            identifier="test-package-1",
            api_endpoint="https://protector.example.com",
            access_key_id="test_key",
            access_secret_key="test_secret",  # noqa: S106
            replace=True,
        )


@patch("voraus_pipeline_utils.methods.protect.requests.post")
def test_protect_wheel_wrapper_timeout(post_request_mock: MagicMock, tmp_path: Path) -> None:
    # Create a dummy wheel file
    wheel_file = tmp_path / "test_wheel.whl"
    wheel_file.write_bytes(b"dummy wheel content")

    # Mock the response to timeout
    post_request_mock.side_effect = requests.Timeout("Request timed out")

    # Call the function and expect a timeout exception
    with pytest.raises(requests.Timeout, match="Request timed out"):
        protect_wheel_wrapper(
            wheel_file=wheel_file,
            identifier="test-package-1",
            api_endpoint="https://protector.example.com",
            access_key_id="test_key",
            access_secret_key="test_secret",  # noqa: S106
            replace=True,
        )


def test_protect_wheel_wrapper_file_not_found() -> None:
    # Test with a non-existent file
    wheel_file = Path("/nonexistent/path/test_wheel.whl")

    with pytest.raises(FileNotFoundError):
        protect_wheel_wrapper(
            wheel_file=wheel_file,
            identifier="test-package-1",
            api_endpoint="https://protector.example.com",
            access_key_id="test_key",
            access_secret_key="test_secret",  # noqa: S106
            replace=True,
        )
