"""6D crm.company.create / update. Upsert/get/search stay unfrozen."""
from __future__ import annotations

from uuid import uuid4

from src.domain.codegen.prompt_wrapper import _app_recipes
from src.domain.connectors.catalog import slugs_implementing
from src.domain.connectors.crm_company import (
    ACTION_BY_CAPABILITY,
    CRM_COMPANY_UPSERT_CLASSIFICATION,
    map_company_capability_input,
    resolve_crm_company,
    to_public_crm_company_result,
)
from src.domain.connectors.crm_company import (
    CRM_COMPANY_FROZEN_VERBS as RUNTIME_VERBS,
)
from src.domain.connectors.crm_resolve import CRMConnectionSnapshot
from src.domain.connectors.invoke_capabilities import (
    CAPABILITY_CONVERSION_PATTERN,
    CRM_COMPANY_FROZEN_VERBS,
    CRM_COMPANY_OUT_OF_SLICE,
    CRM_COMPANY_PHASE_6D,
    CRM_FAMILY_PLAN,
    CRM_HYPOTHESIZED_VERBS_NOT_FROZEN,
    INVOKE_CAPABILITIES,
    is_implemented,
)
from src.domain.connectors.public_gateway import (
    PHASE_6_STATUS,
    PUBLIC_INVOCABLE_CAPABILITIES,
    strip_capability_response,
)
from src.domain.connectors.router import capability_router
from src.main import app

_CAPS = {"integrations.execute"}


def _crm(provider: str, **overrides) -> CRMConnectionSnapshot:
    data = dict(
        connection_id=uuid4(),
        connector_key=provider,
        status="active",
        has_secrets=True,
        permission_mode="allow",
        execution_domain="C",
        requires_secrets=True,
        client_side_only=False,
    )
    data.update(overrides)
    return CRMConnectionSnapshot(**data)


def test_6d_freezes_create_and_update_only() -> None:
    assert PHASE_6_STATUS == "6p_complete"
    assert CAPABILITY_CONVERSION_PATTERN["next_program_slice"] == (
        "9_app_block_modernization"
    )
    assert CRM_FAMILY_PLAN["company_upsert"] == "PROVIDER_SPECIFIC_FOR_NOW"
    assert CRM_COMPANY_PHASE_6D["upsert_classification"] == (
        CRM_COMPANY_UPSERT_CLASSIFICATION
    )
    assert CRM_COMPANY_PHASE_6D["salesforce_website_is_not_domain"] is True
    assert CRM_COMPANY_PHASE_6D["get_search"] == "missing_on_both_providers"
    assert CRM_COMPANY_PHASE_6D["catalog_invocable"] is False
    assert CRM_COMPANY_PHASE_6D["implements_attached"] is False
    assert CRM_COMPANY_PHASE_6D["public_bff_capability_route"] is False
    assert CRM_COMPANY_FROZEN_VERBS == RUNTIME_VERBS
    assert CRM_COMPANY_FROZEN_VERBS == (
        "crm.company.create",
        "crm.company.get",
        "crm.company.update",
        "crm.company.search",
    )
    for verb in CRM_COMPANY_FROZEN_VERBS:
        spec = INVOKE_CAPABILITIES[verb]
        assert spec["status"] == "implemented"
        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)
    for verb in CRM_COMPANY_OUT_OF_SLICE:
        assert verb not in INVOKE_CAPABILITIES
    assert "crm.company.upsert" in CRM_HYPOTHESIZED_VERBS_NOT_FROZEN
    recipes = _app_recipes()
    assert "crm.company.create" in recipes


def test_core_registers_private_company_routes() -> None:
    paths = {getattr(route, "path", "") for route in capability_router.routes}
    for verb in CRM_COMPANY_FROZEN_VERBS:
        expected = f"/api/projects/{{project_id}}/capabilities/{verb}"
        assert expected in paths
        assert expected in {getattr(route, "path", "") for route in app.routes}
    assert "/api/projects/{project_id}/capabilities/crm.company.upsert" not in paths


def test_provider_action_slugs_are_repository_truth() -> None:
    assert ACTION_BY_CAPABILITY["crm.company.create"] == {
        "hubspot": "hubspot.create_company",
        "salesforce": "salesforce.create_account",
    }
    assert ACTION_BY_CAPABILITY["crm.company.update"] == {
        "hubspot": "hubspot.update_company",
        "salesforce": "salesforce.update_account",
    }
    assert ACTION_BY_CAPABILITY["crm.company.get"] == {
        "hubspot": "hubspot.get_company",
        "salesforce": "salesforce.get_account",
    }
    assert ACTION_BY_CAPABILITY["crm.company.search"] == {
        "hubspot": "hubspot.search_companies",
        "salesforce": "salesforce.search_accounts",
    }


def test_hubspot_maps_domain_salesforce_rejects_it() -> None:
    hs = map_company_capability_input(
        "crm.company.create",
        "hubspot",
        {"company": {"name": "Acme", "domain": "acme.com", "phone": "1"}},
    )
    assert isinstance(hs, dict)
    assert hs["properties"] == {
        "name": "Acme",
        "domain": "acme.com",
        "phone": "1",
    }
    sf = map_company_capability_input(
        "crm.company.create",
        "salesforce",
        {"company": {"name": "Acme", "domain": "acme.com"}},
    )
    assert sf == "crm_field_unsupported"
    sf_ok = map_company_capability_input(
        "crm.company.create",
        "salesforce",
        {"company": {"name": "Acme", "phone": "1"}},
    )
    assert isinstance(sf_ok, dict)
    assert sf_ok["fields"] == {"Name": "Acme", "Phone": "1"}
    assert "Website" not in sf_ok["fields"]


def test_update_preserves_omitted_vs_null_and_object_ref() -> None:
    hs = map_company_capability_input(
        "crm.company.update",
        "hubspot",
        {
            "company": {"object_type": "company", "external_id": "99"},
            "changes": {"phone": None, "name": "Acme"},
        },
    )
    assert isinstance(hs, dict)
    assert hs["company_id"] == "99"
    assert hs["properties"]["phone"] is None
    assert hs["properties"]["name"] == "Acme"
    assert "domain" not in hs["properties"]
    contact_ref = resolve_crm_company(
        capability="crm.company.update",
        payload={
            "company": {"object_type": "contact", "external_id": "99"},
            "changes": {"name": "Acme"},
        },
        connections=[_crm("hubspot")],
        enabled_capabilities=_CAPS,
    )
    assert contact_ref.reason_code == "crm_validation_failed"


def test_property_collision_is_rejected() -> None:
    mapped = map_company_capability_input(
        "crm.company.create",
        "hubspot",
        {"company": {"name": "Acme", "properties": {"name": "Other"}}},
    )
    assert mapped == "crm_property_invalid"


def test_resolver_reuses_family_rules() -> None:
    unbound = resolve_crm_company(
        capability="crm.company.create",
        payload={"company": {"name": "Acme"}},
        connections=[_crm("hubspot", execution_domain="P")],
        enabled_capabilities=_CAPS,
    )
    assert unbound.reason_code == "crm_unbound"
    two = resolve_crm_company(
        capability="crm.company.create",
        payload={"company": {"name": "Acme"}},
        connections=[_crm("hubspot"), _crm("hubspot")],
        enabled_capabilities=_CAPS,
        provider_hint="hubspot",
    )
    assert two.reason_code == "binding_ambiguous"
    mixed = resolve_crm_company(
        capability="crm.company.update",
        payload={
            "company": {"object_type": "company", "external_id": "1"},
            "changes": {"name": "Acme"},
        },
        connections=[_crm("hubspot"), _crm("salesforce")],
        enabled_capabilities=_CAPS,
        provider_hint="salesforce",
    )
    assert mixed.ok
    assert mixed.plan is not None
    assert mixed.plan.provider == "salesforce"
    assert mixed.plan.action == "salesforce.update_account"


def test_queued_does_not_fabricate_company_ref() -> None:
    resolution = resolve_crm_company(
        capability="crm.company.create",
        payload={"company": {"name": "Acme"}},
        connections=[_crm("hubspot")],
        enabled_capabilities=_CAPS,
    )
    public = to_public_crm_company_result(
        resolution,
        capability="crm.company.create",
        enqueue={"ok": True, "job_id": "job_1", "status": "queued"},
    ).as_dict()
    assert public == {"capability": "crm.company.create", "status": "queued"}
    stripped = strip_capability_response(
        {**public, "company_id": "123", "job_id": "job_1"}
    )
    assert stripped == public


def test_salesforce_result_normalizes_to_crm_company() -> None:
    resolution = resolve_crm_company(
        capability="crm.company.update",
        payload={
            "company": {"object_type": "company", "external_id": "001xx"},
            "changes": {"name": "Acme"},
        },
        connections=[_crm("salesforce")],
        enabled_capabilities=_CAPS,
    )
    public = to_public_crm_company_result(
        resolution,
        capability="crm.company.update",
        enqueue={
            "ok": True,
            "result": {"id": "001xx", "Name": "Acme", "Phone": None},
        },
    )
    assert public.status == "succeeded"
    assert public.company == {
        "ref": {"object_type": "company", "external_id": "001xx"},
        "name": "Acme",
        "phone": None,
    }
    assert "domain" not in public.company
