import pytest
import os
import sys
from unittest.mock import MagicMock
from dotenv import load_dotenv

# Load env vars from .env (for live tests)
load_dotenv()

# Ensure project root is in path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from slack_bot.llm.base import BaseLLM

@pytest.fixture
def mock_env(monkeypatch):
    """Set fake env vars for testing."""
    monkeypatch.setenv("GEMINI_API_KEY", "fake_key")
    monkeypatch.setenv("SLACK_BOT_TOKEN", "xoxb-fake")
    monkeypatch.setenv("SLACK_SIGNING_SECRET", "fake_secret")
    monkeypatch.setenv("DATA_DIR", "/tmp/butler_test_data")

@pytest.fixture
def mock_llm_response():
    """Factory to create a mock LLM that returns specific text/tools."""
    def _create(response_text="Hello", tool_calls=None):
        llm = MagicMock(spec=BaseLLM)
        # Mock generate_response return value: (text, tool_calls)
        llm.generate_response.return_value = (response_text, tool_calls)
        return llm
    return _create

@pytest.fixture
def clean_context_storage(tmp_path):
    """Provide a clean context storage path."""
    from slack_bot.context.storage import ContextStorage
    # Monkeypatch the CONTEXT_DIR logic or just use a unique channel_id
    # Since ContextStorage uses global config, better to patch the config.DATA_DIR
    # But for unit tests, we can just use a random channel ID and ensure cleanup
    import uuid
    channel_id = f"test_channel_{uuid.uuid4()}"
    storage = ContextStorage(channel_id)
    # Ensure it's empty
    if storage.file_path.exists():
        storage.file_path.unlink()
    yield storage
    # Cleanup
    if storage.file_path.exists():
        storage.file_path.unlink()

@pytest.fixture
def cli_bot_factory():
    """Factory to create CLI bots for testing."""
    def _create(use_real_llm=False, session_id=None, test_data_dir=None):
        from tools.cli_bot import CLIBot
        import tempfile

        # Use temp directory if not specified
        if test_data_dir is None:
            test_data_dir = tempfile.mkdtemp(prefix="butler_test_")

        return CLIBot(
            use_real_llm=use_real_llm,
            session_id=session_id,
            test_data_dir=test_data_dir
        )
    return _create

@pytest.fixture(scope="function")
def isolated_test_data(monkeypatch, tmp_path):
    """Automatically isolate test data for each test function."""
    test_dir = tmp_path / "butler_test"
    test_dir.mkdir()
    monkeypatch.setenv("DATA_DIR", str(test_dir))
    return test_dir
