"""6L Salesforce implementation completeness. Not a new canonical CRM phase."""
from __future__ import annotations

from uuid import uuid4

import pytest

from src.domain.connectors.catalog import get_connector, slugs_implementing
from src.domain.connectors.crm_association import (
    map_association_input,
    resolve_crm_association,
)
from src.domain.connectors.crm_canonical import CRMAssociation
from src.domain.connectors.crm_company import map_company_capability_input
from src.domain.connectors.crm_contact import map_contact_capability_input, resolve_crm_contact
from src.domain.connectors.crm_deal import map_deal_capability_input
from src.domain.connectors.crm_events import (
    CRMAttributedConnection,
    CRMEventError,
    InMemoryCRMEventDedupe,
    ingest_verified_crm_inbound,
    parse_salesforce_cdc_payload,
)
from src.domain.connectors.crm_resolve import CRMConnectionSnapshot
from src.domain.connectors.invoke_capabilities import (
    CAPABILITY_CONVERSION_PATTERN,
    CRM_CONTACT_FROZEN_VERBS,
    CRM_FAMILY_PLAN,
    CRM_SALESFORCE_COMPLETENESS_PHASE_6L,
    INVOKE_CAPABILITIES,
    is_implemented,
)
from src.domain.connectors.public_gateway import (
    PHASE_6_STATUS,
    PUBLIC_INVOCABLE_CAPABILITIES,
    strip_capability_response,
)


def _crm(**overrides) -> CRMConnectionSnapshot:
    data = dict(
        connection_id=uuid4(),
        connector_key="salesforce",
        status="active",
        has_secrets=True,
        permission_mode="allow",
        execution_domain="C",
        requires_secrets=True,
        client_side_only=False,
        config={"org_id": "00Daaa", "instance_url": "https://acme.my.salesforce.com"},
    )
    data.update(overrides)
    return CRMConnectionSnapshot(**data)


def test_6l_closes_salesforce_without_public_truth() -> None:
    assert PHASE_6_STATUS == "6p_complete"
    assert CAPABILITY_CONVERSION_PATTERN["phase_6_status"] == "6p_complete"
    assert CAPABILITY_CONVERSION_PATTERN["next_program_slice"] == (
        "9_app_block_modernization"
    )
    assert CRM_FAMILY_PLAN["status"] == "6p_complete"
    assert CRM_FAMILY_PLAN["next_slice"] == "forms_first_class_product_domain"
    assert CRM_SALESFORCE_COMPLETENESS_PHASE_6L["not_a_new_canonical_phase"] is True
    assert CRM_SALESFORCE_COMPLETENESS_PHASE_6L["login_hosts_are_oauth_only"] is True
    assert CRM_SALESFORCE_COMPLETENESS_PHASE_6L["null_clear"] == "json_null"
    assert CRM_SALESFORCE_COMPLETENESS_PHASE_6L["pipeline"] == "REJECT"
    assert CRM_SALESFORCE_COMPLETENESS_PHASE_6L["catalog_invocable"] is False
    for verb in CRM_CONTACT_FROZEN_VERBS:
        spec = INVOKE_CAPABILITIES[verb]
        assert spec["invocable"] is True
        assert spec["method"] == f"POST /api/projects/{{project_id}}/capabilities/{verb}"
        assert is_implemented(verb) is True
        assert verb in PUBLIC_INVOCABLE_CAPABILITIES
        slugs = slugs_implementing(verb)
        assert any(s.startswith("hubspot.") for s in slugs)
        assert any(s.startswith("salesforce.") for s in slugs)


def test_salesforce_catalog_keeps_instance_and_org_identity() -> None:
    connector = get_connector("salesforce")
    assert connector is not None
    assert connector.version == "01.05.00"
    assert "instance_url" in connector.config_fields
    assert "org_id" in connector.config_fields
    assert "login_host" in connector.config_fields
    assert "environment" in connector.config_fields
    create = next(row for row in connector.actions if row.key == "create_contact")
    assert create.implements == ("crm.contact.create",)
    soql = next(row for row in connector.actions if row.key == "query_soql")
    assert soql.slug == "salesforce.query_soql"
    assert not soql.implements


def test_canonical_contact_upsert_is_email_not_external_id() -> None:
    mapped = map_contact_capability_input(
        "crm.contact.upsert",
        "salesforce",
        {"contact": {"email": "ada@example.com", "first_name": "Ada", "properties": {"Foo__c": 1}}},
    )
    assert isinstance(mapped, dict)
    assert mapped["email"] == "ada@example.com"
    assert mapped["fields"]["Email"] == "ada@example.com"
    assert mapped["fields"]["FirstName"] == "Ada"
    assert mapped["fields"]["Foo__c"] == 1
    assert "external_id_field" not in mapped
    assert "query" not in mapped
    search = map_contact_capability_input(
        "crm.contact.search",
        "salesforce",
        {"email": "O'Brien@example.com"},
    )
    assert isinstance(search, dict)
    assert search["filters"] == {"Email": "O'Brien@example.com"}
    assert "query" not in search


def test_null_clear_stays_json_null_on_salesforce() -> None:
    mapped = map_contact_capability_input(
        "crm.contact.update",
        "salesforce",
        {
            "contact": {"object_type": "contact", "external_id": "003xx"},
            "changes": {"phone": None, "properties": {"Foo__c": None}},
        },
    )
    assert mapped["fields"]["Phone"] is None
    assert mapped["fields"]["Foo__c"] is None


def test_account_domain_and_opportunity_pipeline_stay_rejected() -> None:
    assert (
        map_company_capability_input(
            "crm.company.create",
            "salesforce",
            {"company": {"name": "Acme", "domain": "acme.com"}},
        )
        == "crm_field_unsupported"
    )
    assert (
        map_deal_capability_input(
            "crm.deal.create",
            "salesforce",
            {"deal": {"name": "Renewal", "pipeline": "sales"}},
            config={"stage_map": {"qualified": "Qualification"}},
        )
        == "crm_pipeline_unsupported"
    )
    search = map_company_capability_input(
        "crm.company.search",
        "salesforce",
        {"name": "Acme' OR Name != '"},
    )
    assert isinstance(search, dict)
    assert search["filters"] == {"Name": "Acme' OR Name != '"}
    assert "query" not in search
    deal_search = map_deal_capability_input(
        "crm.deal.search",
        "salesforce",
        {"name": "Renewal", "stage": "qualified"},
        config={"stage_map": {"qualified": "Qualification"}},
    )
    assert isinstance(deal_search, dict)
    assert deal_search["filters"] == {"Name": "Renewal", "StageName": "Qualification"}


def test_salesforce_associations_are_accountid_updates() -> None:
    contact = map_association_input(
        "contact_company",
        "salesforce",
        CRMAssociation.model_validate(
            {
                "from": {"object_type": "contact", "external_id": "003aa"},
                "to": {"object_type": "company", "external_id": "001bb"},
            }
        ),
    )
    assert contact == {"contact_id": "003aa", "fields": {"AccountId": "001bb"}}
    deal = map_association_input(
        "deal_company",
        "salesforce",
        CRMAssociation.model_validate(
            {
                "from": {"object_type": "deal", "external_id": "006cc"},
                "to": {"object_type": "company", "external_id": "001bb"},
            }
        ),
    )
    assert deal == {"opportunity_id": "006cc", "fields": {"AccountId": "001bb"}}
    rejected = resolve_crm_association(
        capability="crm.association.create",
        payload={
            "association": {
                "from": {"object_type": "contact", "external_id": "003aa"},
                "to": {"object_type": "deal", "external_id": "006cc"},
            }
        },
        connections=[_crm()],
        enabled_capabilities={"integrations.execute"},
    )
    assert rejected.reason_code == "crm_association_unsupported"


def test_public_strip_hides_salesforce_transport() -> None:
    stripped = strip_capability_response(
        {
            "capability": "crm.contact.get",
            "status": "succeeded",
            "instance_url": "https://acme.my.salesforce.com",
            "org_id": "00Daaa",
            "login_host": "https://login.salesforce.com",
            "AccountId": "001",
        }
    )
    assert stripped == {"capability": "crm.contact.get", "status": "succeeded"}


def test_cdc_splits_record_ids_and_rejects_lead() -> None:
    drafts = parse_salesforce_cdc_payload(
        {
            "ChangeEventHeader": {
                "entityName": "Contact",
                "changeType": "UPDATE",
                "recordIds": ["003aaa", "003bbb"],
                "transactionKey": "tx1",
                "organizationId": "00Daaa",
                "changedFields": ["/Email", "/Phone"],
                "changeOrigin": "com/p2hs",
                "commitTimestamp": 1,
            },
            "Email": "a@x.com",
        }
    )
    assert [row.external_id for row in drafts] == ["003aaa", "003bbb"]
    assert {row.provider_event_id for row in drafts} == {"tx1:003aaa", "tx1:003bbb"}
    lead = parse_salesforce_cdc_payload(
        {
            "ChangeEventHeader": {
                "entityName": "Lead",
                "changeType": "CREATE",
                "recordIds": ["00Qzzz"],
                "transactionKey": "tx2",
                "organizationId": "00Daaa",
            }
        }
    )
    assert lead[0].event_type.startswith("crm.lead.")
    row = CRMAttributedConnection(
        project_id=uuid4(),
        workspace_id=uuid4(),
        connection=_crm(),
    )
    accepted = ingest_verified_crm_inbound(
        provider="salesforce",
        verified=True,
        payload={
            "ChangeEventHeader": {
                "entityName": "Lead",
                "changeType": "CREATE",
                "recordIds": ["00Qzzz"],
                "transactionKey": "tx3",
                "organizationId": "00Daaa",
            }
        },
        connections=[row],
        dedupe=InMemoryCRMEventDedupe(),
    )
    assert accepted.accepted == []
    assert accepted.ignored


def test_inactive_salesforce_org_is_identified_not_healthy() -> None:
    row = CRMAttributedConnection(
        project_id=uuid4(),
        workspace_id=uuid4(),
        connection=_crm(status="inactive"),
    )
    with pytest.raises(CRMEventError) as err:
        ingest_verified_crm_inbound(
            provider="salesforce",
            verified=True,
            payload={
                "ChangeEventHeader": {
                    "entityName": "Contact",
                    "changeType": "CREATE",
                    "recordIds": ["003aaa"],
                    "transactionKey": "tx4",
                    "organizationId": "00Daaa",
                }
            },
            connections=[row],
            dedupe=InMemoryCRMEventDedupe(),
        )
    assert err.value.code == "crm_connection_inactive"


def test_execution_domain_p_cannot_satisfy_salesforce_crm() -> None:
    result = resolve_crm_contact(
        capability="crm.contact.get",
        payload={"contact": {"object_type": "contact", "external_id": "003xx"}},
        connections=[_crm(execution_domain="P")],
        enabled_capabilities={"integrations.execute"},
    )
    assert result.reason_code == "crm_unbound"
