"""Cloud SDK contract test fixtures and mock response factories."""

from __future__ import annotations

from typing import Any
from unittest.mock import MagicMock

import httpx
import pytest
import respx

from kanoniv.client.client import KanonivAsyncClient, KanonivClient

BASE_URL = "http://test-api.kanoniv.local"
API_KEY = "kn_test_contract"
JOB_ID = "j-contract-001"


# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------

@pytest.fixture()
def mock_api():
    """Activate a respx mock router scoped to the test API base URL."""
    with respx.mock(base_url=BASE_URL, assert_all_called=False) as router:
        yield router


@pytest.fixture()
def client():
    """Sync client with retries disabled (for non-retry tests)."""
    c = KanonivClient(api_key=API_KEY, base_url=BASE_URL, max_retries=0)
    yield c
    c.close()


@pytest.fixture()
def async_client():
    """Async client with retries disabled."""
    return KanonivAsyncClient(api_key=API_KEY, base_url=BASE_URL, max_retries=0)


@pytest.fixture()
def retry_client():
    """Sync client with max_retries=2 for retry/backoff tests."""
    c = KanonivClient(api_key=API_KEY, base_url=BASE_URL, max_retries=2)
    yield c
    c.close()


@pytest.fixture()
def async_retry_client():
    """Async client with max_retries=2 for async retry tests."""
    return KanonivAsyncClient(api_key=API_KEY, base_url=BASE_URL, max_retries=2)


# ---------------------------------------------------------------------------
# Mock object factories (avoid Rust native dependency)
# ---------------------------------------------------------------------------

def make_mock_spec(
    entity_name: str = "customer",
    sources_config: list[dict[str, Any]] | None = None,
    raw_yaml: str = "api_version: '1'\nidentity_version: 1\nentity:\n  name: customer\n",
) -> MagicMock:
    """Return a Spec-like object with .entity, .sources, .raw."""
    spec = MagicMock()
    spec.entity = entity_name
    spec.sources = sources_config or []
    spec.raw = raw_yaml
    return spec


def make_mock_source(
    name: str = "crm",
    rows: list[dict[str, Any]] | None = None,
    primary_key: str = "id",
) -> MagicMock:
    """Return a Source-like object with .name and .to_entities()."""
    if rows is None:
        rows = [{"id": "1", "name": "Alice", "email": "alice@example.com"}]
    source = MagicMock()
    source.name = name
    entities = [
        {
            "id": row.get(primary_key, f"ext-{i}"),
            "external_id": row.get(primary_key, f"ext-{i}"),
            "entity_type": "customer",
            "data": row,
            "source_name": name,
        }
        for i, row in enumerate(rows)
    ]
    source.to_entities = MagicMock(return_value=entities)
    return source


def make_job_run_response(
    job_id: str = JOB_ID,
    status: str = "pending",
) -> dict[str, Any]:
    """Mock response body for POST /v1/jobs/run."""
    return {"id": job_id, "status": status, "job_type": "reconciliation"}


def make_completed_job_response(job_id: str = JOB_ID) -> dict[str, Any]:
    """Mock response body for a completed job (GET /v1/jobs/:id)."""
    return {
        "id": job_id,
        "status": "completed",
        "job_type": "reconciliation",
        "result": {
            "stats": {
                "canonicals_created": 42,
                "links_created": 87,
                "duration_ms": 1234,
                "identity_summary": {
                    "input": {"total_entities": 100, "sources": 2},
                    "output": {
                        "canonical_identities": 42,
                        "merge_rate": 0.58,
                    },
                    "match_quality": {
                        "accepted": 87,
                        "rejected": 5,
                        "review": 3,
                    },
                    "health_flags": ["low_confidence_cluster"],
                },
                "run_health": {
                    "status": "degraded",
                    "warnings": ["5 low-confidence clusters"],
                },
            },
        },
    }
