"""Pytest configuration and shared fixtures."""

from __future__ import annotations

import json
import os
import subprocess
import tempfile
from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest


@pytest.fixture
def temp_dir():
    """Create a temporary directory for tests."""
    with tempfile.TemporaryDirectory() as tmpdir:
        yield Path(tmpdir)


@pytest.fixture
def temp_git_repo(temp_dir):
    """Create a temporary git repository."""
    subprocess.run(
        ["git", "init"],
        cwd=temp_dir,
        capture_output=True,
        check=True,
    )
    subprocess.run(
        ["git", "config", "user.email", "test@example.com"],
        cwd=temp_dir,
        capture_output=True,
        check=True,
    )
    subprocess.run(
        ["git", "config", "user.name", "Test User"],
        cwd=temp_dir,
        capture_output=True,
        check=True,
    )
    # Create initial commit
    readme = temp_dir / "README.md"
    readme.write_text("# Test Project\n")
    subprocess.run(["git", "add", "."], cwd=temp_dir, capture_output=True, check=True)
    subprocess.run(
        ["git", "commit", "-m", "Initial commit"],
        cwd=temp_dir,
        capture_output=True,
        check=True,
    )
    yield temp_dir


@pytest.fixture
def sample_pyproject(temp_dir):
    """Create a sample pyproject.toml with glreview config."""
    config = {
        "tool": {
            "glreview": {
                "sources": ["src/**/*.py"],
                "exclude": ["**/_version.py", "**/test_*.py"],
                "registry": "review_registry.json",
            }
        }
    }
    pyproject_path = temp_dir / "pyproject.toml"
    # Write as TOML format
    content = """[tool.glreview]
sources = ["src/**/*.py"]
exclude = ["**/_version.py", "**/test_*.py"]
registry = "review_registry.json"
"""
    pyproject_path.write_text(content)
    return pyproject_path


@pytest.fixture
def sample_source_files(temp_dir):
    """Create sample Python source files for testing."""
    src_dir = temp_dir / "src" / "mypackage"
    src_dir.mkdir(parents=True)

    # __init__.py
    init_file = src_dir / "__init__.py"
    init_file.write_text('"""My package."""\n\n__version__ = "0.1.0"\n')

    # main.py
    main_file = src_dir / "main.py"
    main_file.write_text('''"""Main module."""


def hello(name: str) -> str:
    """Say hello."""
    return f"Hello, {name}!"


class Greeter:
    """A greeter class."""

    def __init__(self, prefix: str = "Hello"):
        self.prefix = prefix

    def greet(self, name: str) -> str:
        """Greet someone."""
        return f"{self.prefix}, {name}!"
''')

    # utils.py
    utils_file = src_dir / "utils.py"
    utils_file.write_text('''"""Utility functions."""


def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b


def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b
''')

    return {
        "init": init_file,
        "main": main_file,
        "utils": utils_file,
    }


@pytest.fixture
def sample_registry_data():
    """Sample registry data for testing."""
    return {
        "version": "1.0",
        "last_sync_commit": "abc123",
        "modules": {
            "src/mypackage/__init__.py": {
                "path": "src/mypackage/__init__.py",
                "status": "needs_review",
                "priority": "low",
                "lines": 3,
                "reviewers_required": 1,
                "reviewers": [],
                "last_reviewed_commit": None,
                "last_reviewed_date": None,
                "review_issue": None,
                "assigned_reviewer": None,
                "review_started_commit": None,
                "notes": None,
            },
            "src/mypackage/main.py": {
                "path": "src/mypackage/main.py",
                "status": "in_progress",
                "priority": "high",
                "lines": 20,
                "reviewers_required": 1,
                "reviewers": [],
                "last_reviewed_commit": None,
                "last_reviewed_date": None,
                "review_issue": "#123",
                "assigned_reviewer": "@reviewer",
                "review_started_commit": "def456",
                "notes": None,
            },
            "src/mypackage/utils.py": {
                "path": "src/mypackage/utils.py",
                "status": "reviewed",
                "priority": "medium",
                "lines": 15,
                "reviewers_required": 1,
                "reviewers": ["@alice", "@bob"],
                "last_reviewed_commit": "ghi789",
                "last_reviewed_date": "2024-01-15",
                "review_issue": None,
                "assigned_reviewer": None,
                "review_started_commit": None,
                "notes": None,
            },
        },
    }


@pytest.fixture
def sample_registry_file(temp_dir, sample_registry_data):
    """Create a sample registry file."""
    registry_path = temp_dir / "review_registry.json"
    registry_path.write_text(json.dumps(sample_registry_data, indent=2))
    return registry_path


@pytest.fixture
def mock_gitlab():
    """Mock GitLab client for testing."""
    with patch("glreview.gitlab.gitlab") as mock_gitlab_module:
        mock_gl = MagicMock()
        mock_gitlab_module.Gitlab.return_value = mock_gl
        yield mock_gl


@pytest.fixture
def mock_subprocess():
    """Mock subprocess.run for testing git commands."""
    with patch("subprocess.run") as mock_run:
        mock_result = MagicMock()
        mock_result.returncode = 0
        mock_result.stdout = ""
        mock_result.stderr = ""
        mock_run.return_value = mock_result
        yield mock_run


@pytest.fixture
def env_with_gitlab_token():
    """Set up environment with GitLab token."""
    old_token = os.environ.get("GITLAB_PRIVATE_TOKEN")
    os.environ["GITLAB_PRIVATE_TOKEN"] = "test-token-123"
    yield
    if old_token is not None:
        os.environ["GITLAB_PRIVATE_TOKEN"] = old_token
    else:
        os.environ.pop("GITLAB_PRIVATE_TOKEN", None)
