"""Shared test fixtures for codeflash-service."""

from __future__ import annotations

import os
import sys
from pathlib import Path
from unittest.mock import MagicMock

import httpx
import pytest
import stamina

sys.path.insert(0, str(Path(__file__).resolve().parent))

from helpers import FAKE_RSA_PEM, WEBHOOK_SECRET, sign_payload  # noqa: E402

__all__ = ["FAKE_RSA_PEM", "WEBHOOK_SECRET", "sign_payload"]


@pytest.fixture(autouse=True, scope="session")
def set_env():
    """Set required env vars so Config() can be instantiated."""
    os.environ.setdefault("GITHUB_APP_ID", "12345")
    os.environ.setdefault("GITHUB_PRIVATE_KEY", FAKE_RSA_PEM)
    os.environ.setdefault("GITHUB_WEBHOOK_SECRET", WEBHOOK_SECRET)


@pytest.fixture(autouse=True, scope="session")
def deactivate_retries():
    """Disable stamina retries for fast tests."""
    stamina.set_active(False)


@pytest.fixture(autouse=True)
def clear_token_cache():
    """Clear the installation token cache between tests."""
    from github_app.auth import token_cache

    token_cache.clear()


@pytest.fixture()
def mock_config():
    """A mock Config with all required fields."""
    cfg = MagicMock()
    cfg.app_id = 12345
    cfg.private_key = FAKE_RSA_PEM
    cfg.webhook_secret = WEBHOOK_SECRET
    cfg.claude_cli = "claude"
    cfg.claude_model = "claude-sonnet-4-6"
    cfg.plugin_dir = Path("/tmp/plugins")
    cfg.codex_cli = "codex"
    cfg.codex_model = "gpt-5.4"
    cfg.lead_backend = "claude"
    cfg.cli_for_backend = lambda name: {
        "claude": cfg.claude_cli,
        "codex": cfg.codex_cli,
    }[name]
    cfg.model_for_backend = lambda name: {
        "claude": cfg.claude_model,
        "codex": cfg.codex_model,
    }[name]
    cfg.host = "0.0.0.0"
    cfg.port = 8000
    cfg.workspace_dir = Path("/tmp/codeflash-workspaces")
    return cfg


@pytest.fixture()
def pr_payload():
    """Minimal pull_request webhook payload."""
    return {
        "action": "opened",
        "pull_request": {
            "number": 42,
            "title": "Test PR",
            "head": {"ref": "feature-branch"},
            "base": {"ref": "main"},
        },
        "repository": {
            "name": "test-repo",
            "owner": {"login": "test-owner"},
            "default_branch": "main",
        },
        "installation": {"id": 99},
    }


@pytest.fixture()
def issue_payload():
    """Minimal issues webhook payload."""
    return {
        "action": "opened",
        "issue": {
            "number": 7,
            "title": "Bug: something broken",
            "body": "Steps to reproduce...",
            "labels": [],
        },
        "repository": {
            "name": "test-repo",
            "owner": {"login": "test-owner"},
            "default_branch": "main",
        },
        "installation": {"id": 99},
    }


@pytest.fixture()
def push_payload():
    """Minimal push webhook payload."""
    return {
        "ref": "refs/heads/main",
        "after": "abc123",
        "repository": {
            "name": "test-repo",
            "owner": {"login": "test-owner"},
            "default_branch": "main",
        },
        "installation": {"id": 99},
    }


@pytest.fixture()
async def async_client(mock_config):
    """ASGI test client with app state pre-populated."""
    from github_app.app import app

    mock_http = httpx.AsyncClient()
    app.state.config = mock_config
    app.state.http_client = mock_http
    app.state.running_tasks = set()

    async with httpx.AsyncClient(
        transport=httpx.ASGITransport(app=app),
        base_url="http://test",
    ) as client:
        yield client

    await mock_http.aclose()
