"""Integration tests for 1Password CLI integration.

These tests require:
1. 1Password CLI installed (op command available)
2. User authenticated (op signin completed)
3. Test vault and items set up in 1Password

Run with: pytest --run-integration
Skip with: pytest -m "not integration"
"""

import subprocess

import pytest

from scottzach1.onepassword_cli import (
    OnePasswordSettings,
    inject_dictionary_1password,
    inject_string_1password,
)


def check_op_available() -> bool:
    """Check if 1Password CLI is available and user is authenticated."""
    try:
        result = subprocess.run(["op", "--version"], capture_output=True, check=False, timeout=5)
        if result.returncode != 0:
            return False
        result = subprocess.run(["op", "account", "list"], capture_output=True, check=False, timeout=5)
        return result.returncode == 0
    except (FileNotFoundError, subprocess.TimeoutExpired):
        return False


pytestmark = pytest.mark.integration
skip_if_no_op = pytest.mark.skipif(
    not check_op_available(),
    reason="1Password CLI not available or not authenticated",
)


@skip_if_no_op
class TestIntegrationInjectString:
    """Integration tests for inject_string_1password.

    Note: These tests require a test vault with known items.
    Modify the op:// references below to match your test environment.
    """

    def test_no_secrets_integration(self) -> None:
        """Test string without secrets (no CLI call should be made)."""
        result = inject_string_1password("Just a plain string")
        assert result == "Just a plain string"

    @pytest.mark.skip(reason="Requires manual setup of test vault and items")
    def test_inject_real_secret(self) -> None:
        """Test injection of a real secret from 1Password.

        To use this test:
        1. Create a test vault in 1Password
        2. Create a test item with a field
        3. Update the op:// reference below
        """
        # Example: result = inject_string_1password("op://TestVault/TestItem/password")
        # assert result != "op://TestVault/TestItem/password"
        # assert len(result) > 0
        pytest.skip("Test vault not configured")


@skip_if_no_op
class TestIntegrationInjectDictionary:
    """Integration tests for inject_dictionary_1password."""

    def test_no_secrets_integration(self) -> None:
        """Test dictionary without secrets."""
        data = {"host": "localhost", "port": 5432, "debug": True}
        result = inject_dictionary_1password(data)
        assert result == data

    def test_type_preservation_integration(self) -> None:
        """Test that types are preserved through the injection process."""
        data = {
            "string": "value",
            "integer": 42,
            "float": 3.14,
            "boolean": True,
            "none": None,
            "list": [1, 2, 3],
            "nested": {"key": "value", "count": 10},
        }
        result = inject_dictionary_1password(data)
        assert result == data
        assert isinstance(result["integer"], int)
        assert isinstance(result["float"], float)
        assert isinstance(result["boolean"], bool)
        assert result["none"] is None
        assert isinstance(result["list"], list)
        assert isinstance(result["nested"], dict)

    @pytest.mark.skip(reason="Requires manual setup of test vault and items")
    def test_inject_real_secrets_dict(self) -> None:
        """Test injection of real secrets in a dictionary.

        To use this test:
        1. Create a test vault in 1Password
        2. Create test items with fields
        3. Update the op:// references below
        """
        # Example:
        # data = {
        #     "api_key": "op://TestVault/API/key",
        #     "password": "op://TestVault/Database/password",
        #     "port": 5432,
        # }
        # result = inject_dictionary_1password(data)
        # assert result["api_key"] != "op://TestVault/API/key"
        # assert result["password"] != "op://TestVault/Database/password"
        # assert result["port"] == 5432
        pytest.skip("Test vault not configured")


@skip_if_no_op
class TestIntegrationSettings:
    """Integration tests for OnePasswordSettings."""

    def test_settings_without_secrets(self) -> None:
        """Test settings without any secrets."""

        class TestSettings(OnePasswordSettings):
            host: str = "localhost"
            port: int = 8080

        settings = TestSettings()
        assert settings.host == "localhost"
        assert settings.port == 8080

    @pytest.mark.skip(reason="Requires manual setup of test vault and items")
    def test_settings_with_real_secrets(self) -> None:
        """Test settings with real secret injection.

        To use this test:
        1. Create a test vault in 1Password
        2. Create test items with fields
        3. Update the op:// references below
        """
        # Example:
        # class TestSettings(OnePasswordSettings):
        #     api_key: str
        #     database_url: str
        #     port: int = 5432
        #
        # settings = TestSettings(
        #     api_key="op://TestVault/API/key",
        #     database_url="op://TestVault/Database/url",
        # )
        # assert settings.api_key != "op://TestVault/API/key"
        # assert settings.database_url != "op://TestVault/Database/url"
        # assert settings.port == 5432
        pytest.skip("Test vault not configured")


class TestIntegrationCLINotAvailable:
    """Integration tests for error handling when CLI is not available."""

    def test_cli_check_when_authenticated(self) -> None:
        """Test that CLI checks pass when properly authenticated."""
        if not check_op_available():
            pytest.skip("1Password CLI not available for this test")

        # This should not raise an exception
        result = inject_string_1password("no secrets here", check_cli=True)
        assert result == "no secrets here"
