"""Chaos: Over-Merge (MOST IMPORTANT).

Proving: "Shared identifiers do NOT collapse unrelated entities into one."
The golden rule: prefer false negatives over false positives.
Requires native extension with reconcile_local.
"""
from __future__ import annotations

import pytest

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

pytestmark = requires_reconcile


# ---------------------------------------------------------------------------
# Spec variants
# ---------------------------------------------------------------------------

EMAIL_ONLY_SPEC = """\
api_version: kanoniv/v2
identity_version: test_v1.0
entity:
  name: customer
sources:
  - name: main
    system: csv
    table: main
    id: id
    attributes:
      email: email
      first_name: first_name
      last_name: last_name
      phone: phone
blocking:
  strategy: composite
  keys:
    - [email]
rules:
  - name: email_exact
    type: exact
    field: email
    weight: 1.0
decision:
  thresholds:
    match: 0.7
    review: 0.4
  conflict_strategy: prefer_high_confidence
"""

PHONE_ONLY_SPEC = """\
api_version: kanoniv/v2
identity_version: test_v1.0
entity:
  name: customer
sources:
  - name: main
    system: csv
    table: main
    id: id
    attributes:
      email: email
      first_name: first_name
      last_name: last_name
      phone: phone
blocking:
  strategy: composite
  keys:
    - [phone]
rules:
  - name: phone_exact
    type: exact
    field: phone
    weight: 1.0
decision:
  thresholds:
    match: 0.7
    review: 0.4
  conflict_strategy: prefer_high_confidence
"""

HIGH_THRESHOLD_SPEC = """\
api_version: kanoniv/v2
identity_version: test_v1.0
entity:
  name: customer
sources:
  - name: main
    system: csv
    table: main
    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: 0.4
  - name: phone_exact
    type: exact
    field: phone
    weight: 0.4
decision:
  thresholds:
    match: 0.95
    review: 0.5
  conflict_strategy: prefer_high_confidence
"""


# ---------------------------------------------------------------------------
# Over-merge tests
# ---------------------------------------------------------------------------


class TestOverMerge:
    def test_family_shared_phone_no_collapse(self):
        """4 family members, same phone, different names/emails → NOT 1 cluster."""
        from kanoniv.reconcile import reconcile
        from kanoniv.source import Source

        src = Source.from_csv("main", golden_path("family_shared_phone.csv"), primary_key="id")
        spec = make_spec(PHONE_ONLY_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count >= 1

    def test_corporate_shared_inbox(self):
        """5 employees, shared info@acme.com → consistent behavior."""
        from kanoniv.reconcile import reconcile
        from kanoniv.source import Source

        src = Source.from_csv("main", golden_path("corporate_shared_inbox.csv"), primary_key="id")
        spec = make_spec(EMAIL_ONLY_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count >= 1

    def test_call_center_shared_phone(self, tmp_path):
        """10 records, same phone, unique emails → 10 clusters with email-only spec."""
        from kanoniv.reconcile import reconcile

        rows = [
            {"id": str(i), "email": f"agent{i}@callcenter.com",
             "first_name": f"Agent{i}", "last_name": f"Last{i}",
             "phone": "555-0000"}
            for i in range(1, 11)
        ]
        src = make_source(tmp_path, "main", rows)
        spec = make_spec(EMAIL_ONLY_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count == 10

    def test_roommates_shared_address(self, tmp_path):
        """3 people, same phone (as address proxy), different emails → 3 clusters."""
        from kanoniv.reconcile import reconcile

        rows = [
            {"id": "1", "email": "alice@example.com", "first_name": "Alice",
             "last_name": "Smith", "phone": "555-HOME"},
            {"id": "2", "email": "bob@example.com", "first_name": "Bob",
             "last_name": "Jones", "phone": "555-HOME"},
            {"id": "3", "email": "carol@example.com", "first_name": "Carol",
             "last_name": "Brown", "phone": "555-HOME"},
        ]
        src = make_source(tmp_path, "main", rows)
        spec = make_spec(EMAIL_ONLY_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count == 3

    def test_shared_phone_with_email_spec(self, tmp_path):
        """Email spec + shared phone → phone alone insufficient for merge."""
        from kanoniv.reconcile import reconcile

        rows = [
            {"id": "1", "email": "alice@example.com", "first_name": "Alice",
             "last_name": "Smith", "phone": "555-0000"},
            {"id": "2", "email": "bob@example.com", "first_name": "Bob",
             "last_name": "Jones", "phone": "555-0000"},
        ]
        src = make_source(tmp_path, "main", rows)
        spec = make_spec(EMAIL_ONLY_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count == 2

    def test_high_threshold_prevents_overmerge(self, tmp_path):
        """match: 0.95 with weak signals → no false merges."""
        from kanoniv.reconcile import reconcile

        rows = [
            {"id": "1", "email": "alice@example.com", "first_name": "Alice",
             "last_name": "Smith", "phone": "555-0001"},
            {"id": "2", "email": "bob@example.com", "first_name": "Bob",
             "last_name": "Jones", "phone": "555-0001"},
        ]
        src = make_source(tmp_path, "main", rows)
        spec = make_spec(HIGH_THRESHOLD_SPEC)
        result = reconcile([src], spec)
        assert result.cluster_count == 2
