"""6B frozen external CRM vocabulary. No crm.* invoke verbs."""
from __future__ import annotations

import pytest
from pydantic import ValidationError
from src.domain.connectors.catalog import slugs_implementing
from src.domain.connectors.crm_canonical import (
    CANONICAL_COLLISION,
    CANONICAL_NULL_MEANS,
    CANONICAL_OMITTED_MEANS,
    CRM_CANONICAL_MODEL,
    CRM_FIELD_MAP,
    P2HS_RECORD_ENTITY_KEYS,
    CRMAssociation,
    CRMCanonicalError,
    CRMCompanyInput,
    CRMContact,
    CRMContactInput,
    CRMDealInput,
    CRMObjectRef,
    assert_property_map,
    dump_crm_input,
)
from src.domain.connectors.invoke_capabilities import (
    CAPABILITY_CONVERSION_PATTERN,
    CRM_FAMILY_PLAN,
    CRM_HYPOTHESIZED_VERBS_NOT_FROZEN,
    INVOKE_CAPABILITIES,
)
from src.domain.connectors.public_gateway import (
    PHASE_6_STATUS,
    PUBLIC_INVOCABLE_CAPABILITIES,
)


def test_6b_freezes_model_not_capabilities() -> None:
    pattern = CAPABILITY_CONVERSION_PATTERN
    assert PHASE_6_STATUS == "6p_complete"
    assert pattern["phase_6_status"] == "6p_complete"
    assert pattern["next_program_slice"] == "9_app_block_modernization"
    assert pattern["opened_families"]["crm.*"] == "canonical_model"
    assert CRM_FAMILY_PLAN["object_model_frozen"] is True
    assert CRM_FAMILY_PLAN["verbs_frozen"] is False
    assert CRM_FAMILY_PLAN["contact_verbs_frozen"] is True
    assert CRM_FAMILY_PLAN["company_verbs_frozen"] is True
    assert CRM_FAMILY_PLAN["deal_verbs_frozen"] is True
    assert CRM_FAMILY_PLAN["status"] == "6p_complete"
    assert CRM_CANONICAL_MODEL["salesforce_lead_is_not_crm_contact"] is True
    assert CRM_CANONICAL_MODEL["crm_lead_app_block_is_p2hs_records"] is True
    assert CRM_CANONICAL_MODEL["deferred_types"] == {
        "CRMNote": "defer",
        "CRMTask": "provider_specific_for_now",
        "CRMActivity": "reject_umbrella",
    }
    for verb in CRM_HYPOTHESIZED_VERBS_NOT_FROZEN:
        assert verb not in INVOKE_CAPABILITIES
        assert verb not in PUBLIC_INVOCABLE_CAPABILITIES
        assert slugs_implementing(verb) == ()


def test_property_map_rejects_collision_and_nested_values() -> None:
    assert CANONICAL_COLLISION == "reject"
    assert CANONICAL_NULL_MEANS == "clear"
    assert CANONICAL_OMITTED_MEANS == "unchanged_or_unspecified"
    with pytest.raises(CRMCanonicalError) as collision:
        assert_property_map({"email": "other@example.com"}, object_type="contact")
    assert collision.value.code == "canonical_property_collision"
    with pytest.raises(CRMCanonicalError) as nested:
        assert_property_map({"tags": ["a"]}, object_type="contact")
    assert nested.value.code == "unsupported_property_value"
    assert_property_map(
        {"custom_field": "x", "count": 1, "ok": True, "gone": None},
        object_type="contact",
    )
    with pytest.raises(ValidationError):
        CRMContactInput(email="a@example.com", properties={"email": "b@example.com"})


def test_omitted_vs_null_dump() -> None:
    omitted = dump_crm_input(CRMContactInput.model_validate({"first_name": "Ada"}))
    assert omitted == {"first_name": "Ada"}
    cleared = dump_crm_input(CRMContactInput.model_validate({"phone": None}))
    assert cleared == {"phone": None}


def test_object_ref_is_external_crm_only() -> None:
    ref = CRMObjectRef(object_type="contact", external_id="123")
    assert "lead" not in CRM_CANONICAL_MODEL["object_types"]
    for key in P2HS_RECORD_ENTITY_KEYS:
        assert key not in CRM_CANONICAL_MODEL["object_types"]
    with pytest.raises(ValidationError):
        CRMObjectRef(object_type="lead", external_id="abc")
    contact = CRMContact(ref=ref, email="ada@example.com", first_name="Ada")
    assert contact.ref.object_type == "contact"
    link = CRMAssociation.model_validate(
        {
            "from": {"object_type": "contact", "external_id": "1"},
            "to": {"object_type": "company", "external_id": "2"},
        }
    )
    assert "relationship" not in link.model_dump(by_alias=True)


def test_company_and_deal_mappings_reject_weak_equivalences() -> None:
    by_field = {row["field"]: row for row in CRM_FIELD_MAP}
    assert by_field["CRMCompany.domain"]["salesforce"] is None
    assert by_field["CRMDeal.pipeline"]["strong"] is False
    assert by_field["CRMDeal.stage"]["strong"] is True
    assert CRM_CANONICAL_MODEL["pipeline_stage"] == "logical_aliases_connection_scoped"
    deal = CRMDealInput(name="Pilot", amount=12000, pipeline="sales", stage="qualified")
    assert deal.pipeline == "sales"
    company = CRMCompanyInput(name="Acme", domain="acme.com")
    assert company.domain == "acme.com"
    assert CRM_CANONICAL_MODEL["get_not_implied_by_object"] is True
    assert CRM_CANONICAL_MODEL["email_required"] == "email_upsert_only"
