"""Chaos: Observability Failure.

Proving: "Silent success is not allowed — results must explain why."
Requires native extension with reconcile_local.
"""
from __future__ import annotations

import pytest

from tests.contract.conftest import (
    SINGLE_SOURCE_SPEC,
    make_source,
    make_spec,
    requires_reconcile,
)

pytestmark = requires_reconcile


# ---------------------------------------------------------------------------
# Edge-case observability
# ---------------------------------------------------------------------------


class TestObservabilityEdgeCases:
    def test_empty_source_returns_zero_clusters(self, tmp_path):
        """0 records → cluster_count == 0."""
        from kanoniv.reconcile import reconcile

        src = make_source(tmp_path, "main", [])
        spec = make_spec(SINGLE_SOURCE_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count == 0

    def test_empty_source_telemetry_exists(self, tmp_path):
        """0 records → telemetry still populated."""
        from kanoniv.reconcile import reconcile

        src = make_source(tmp_path, "main", [])
        spec = make_spec(SINGLE_SOURCE_SPEC)
        result = reconcile([src], spec)
        assert isinstance(result.telemetry, dict)

    def test_single_record_singleton_cluster(self, tmp_path):
        """1 record → 1 cluster, merge_rate == 0.0."""
        from kanoniv.reconcile import reconcile

        rows = [
            {"id": "1", "email": "solo@example.com", "first_name": "Solo",
             "last_name": "Person", "phone": "555-0001"},
        ]
        src = make_source(tmp_path, "main", rows)
        spec = make_spec(SINGLE_SOURCE_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count == 1
        assert result.merge_rate == 0.0

    def test_zero_matches_decisions_empty_or_rejects(self, tmp_path):
        """No overlaps → decisions list empty or all rejects."""
        from kanoniv.reconcile import reconcile

        rows = [
            {"id": "1", "email": "a@example.com", "first_name": "Alice",
             "last_name": "Smith", "phone": "555-0001"},
            {"id": "2", "email": "b@example.com", "first_name": "Bob",
             "last_name": "Jones", "phone": "555-0002"},
        ]
        src = make_source(tmp_path, "main", rows)
        spec = make_spec(SINGLE_SOURCE_SPEC)
        result = reconcile([src], spec)
        for d in result.decisions:
            decision_type = d.get("decision", d.get("type", ""))
            assert decision_type != "merge", (
                f"Unexpected merge decision with no overlapping data: {d}"
            )

    def test_telemetry_pairs_for_disjoint_sources(self, tmp_path):
        """Disjoint sources → telemetry exists and cluster count is correct."""
        from kanoniv.reconcile import reconcile

        rows_a = [
            {"id": "1", "email": "a@example.com", "first_name": "A",
             "last_name": "Smith", "phone": "555-0001"},
        ]
        rows_b = [
            {"id": "2", "email": "b@example.com", "first_name": "B",
             "last_name": "Jones", "phone": "555-0002"},
        ]
        src_a = make_source(tmp_path, "crm", rows_a)
        src_b = make_source(tmp_path, "ecommerce", rows_b)

        spec_yaml = """\
api_version: kanoniv/v2
identity_version: test_v1.0
entity:
  name: customer
sources:
  - name: crm
    system: csv
    table: crm
    id: id
    attributes:
      email: email
      first_name: first_name
      last_name: last_name
      phone: phone
  - name: ecommerce
    system: csv
    table: ecommerce
    id: id
    attributes:
      email: email
      first_name: first_name
      last_name: last_name
      phone: phone
blocking:
  strategy: composite
  keys:
    - [email]
    - [phone]
rules:
  - name: email_exact
    type: exact
    field: email
    weight: 1.0
decision:
  thresholds:
    match: 0.7
    review: 0.4
  conflict_strategy: prefer_high_confidence
"""
        spec = make_spec(spec_yaml)
        result = reconcile([src_a, src_b], spec)
        assert result.cluster_count == 2
        assert isinstance(result.telemetry, dict)
