"""Shared test fixtures for fw-nodes-forgejo tests."""

from typing import Any
from uuid import uuid4

import pytest
from flowire_sdk import NodeExecutionContext


class MockExecutionContext(NodeExecutionContext):
    """Mock execution context for testing nodes."""

    def __init__(
        self,
        workflow_id: str | None = None,
        execution_id: str | None = None,
        node_id: str | None = None,
        project_id: str | None = None,
        user_id: str | None = None,
        node_results: dict[str, dict[str, Any]] | None = None,
        project_variables: dict[str, Any] | None = None,
        credentials: dict[str, dict] | None = None,
        binary_store: dict[str, bytes] | None = None,
    ):
        self.workflow_id = workflow_id or str(uuid4())
        self.execution_id = execution_id or str(uuid4())
        self.node_id = node_id or "test_node"
        self.project_id = project_id or str(uuid4())
        self.user_id = user_id or str(uuid4())
        self.node_results = node_results or {}
        self._secrets: set[str] = set()
        self._project_variables = project_variables or {}
        self._credentials = credentials or {}
        self._binary_store: dict[str, bytes] = binary_store or {}

    async def resolve_credential(self, credential_id: str, credential_type: str) -> dict:
        if credential_id in self._credentials:
            return self._credentials[credential_id]
        raise ValueError(f"Credential {credential_id} not found")

    async def resolve_credential_by_id(self, credential_id: str) -> dict:
        if credential_id in self._credentials:
            return self._credentials[credential_id]
        raise ValueError(f"Credential {credential_id} not found")

    async def resolve_project_variable(self, key: str) -> Any:
        if key in self._project_variables:
            return self._project_variables[key]
        raise ValueError(f"Project variable {key} not found")

    async def resolve_project_variable_by_id(self, variable_id: str) -> Any:
        if variable_id in self._project_variables:
            return self._project_variables[variable_id]
        raise ValueError(f"Project variable {variable_id} not found")

    def register_secret(self, value: str) -> None:
        if value:
            self._secrets.add(value)

    def get_secrets(self) -> set:
        return self._secrets

    def store_binary(
        self,
        data: bytes,
        filename: str,
        content_type: str = "application/octet-stream",
        metadata: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        uri = f"storage://test/{self.project_id}/{filename}"
        self._binary_store[uri] = data
        return {
            "_type": "storage_reference",
            "uri": uri,
            "metadata": {"content_type": content_type, **(metadata or {})},
        }

    def retrieve_binary(self, reference: dict[str, Any]) -> bytes:
        uri = reference.get("uri", "")
        if uri not in self._binary_store:
            raise ValueError(f"Storage reference not found: {uri}")
        return self._binary_store[uri]

    def publish_webhook_error(self, error: str, status_code: int = 400) -> None:
        pass

    def publish_immediate_response(
        self,
        status_code: int = 200,
        body: Any = None,
        content_type: str = "application/json",
        headers: dict[str, str] | None = None,
    ) -> None:
        pass


@pytest.fixture
def mock_context():
    """Create a MockExecutionContext for testing."""
    return MockExecutionContext(
        workflow_id="wf_123",
        execution_id="exec_456",
        node_id="node_789",
        project_id="proj_abc",
        user_id="user_xyz",
        node_results={},
    )
