"""6E crm.deal.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_deal import (
    ACTION_BY_CAPABILITY,
    CRM_DEAL_UPSERT_CLASSIFICATION,
    dispatch_crm_deal_plan,
    map_deal_capability_input,
    resolve_crm_deal,
    to_public_crm_deal_result,
)
from src.domain.connectors.crm_deal import (
    CRM_DEAL_FROZEN_VERBS as RUNTIME_VERBS,
)
from src.domain.connectors.crm_resolve import CRMConnectionSnapshot, DispatchAuthorization
from src.domain.connectors.invoke_capabilities import (
    CAPABILITY_CONVERSION_PATTERN,
    CRM_DEAL_FROZEN_VERBS,
    CRM_DEAL_OUT_OF_SLICE,
    CRM_DEAL_PHASE_6E,
    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"}
_HS_CONFIG = {
    "stage_map": {"qualified": "appointmentscheduled"},
    "pipeline_map": {"sales": "default"},
}
_SF_CONFIG = {"stage_map": {"qualified": "Prospecting"}}


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_6e_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["deal_upsert"] == "PROVIDER_SPECIFIC_FOR_NOW"
    assert CRM_DEAL_PHASE_6E["upsert_classification"] == CRM_DEAL_UPSERT_CLASSIFICATION
    assert CRM_DEAL_PHASE_6E["salesforce_pipeline_is_not_record_type"] is True
    assert CRM_DEAL_PHASE_6E["no_canonical_currency"] is True
    assert CRM_DEAL_PHASE_6E["get_search"] == "missing_on_both_providers"
    assert CRM_DEAL_PHASE_6E["catalog_invocable"] is False
    assert CRM_DEAL_PHASE_6E["implements_attached"] is False
    assert CRM_DEAL_PHASE_6E["public_bff_capability_route"] is False
    assert CRM_DEAL_FROZEN_VERBS == RUNTIME_VERBS
    assert CRM_DEAL_FROZEN_VERBS == (
        "crm.deal.create",
        "crm.deal.get",
        "crm.deal.update",
        "crm.deal.search",
    )
    for verb in CRM_DEAL_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_DEAL_OUT_OF_SLICE:
        assert verb not in INVOKE_CAPABILITIES
    assert "crm.deal.upsert" in CRM_HYPOTHESIZED_VERBS_NOT_FROZEN
    recipes = _app_recipes()
    assert "crm.deal.create" in recipes


def test_core_registers_private_deal_routes() -> None:
    paths = {getattr(route, "path", "") for route in capability_router.routes}
    for verb in CRM_DEAL_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.deal.upsert" not in paths


def test_provider_action_slugs_are_repository_truth() -> None:
    assert ACTION_BY_CAPABILITY["crm.deal.create"] == {
        "hubspot": "hubspot.create_deal",
        "salesforce": "salesforce.create_opportunity",
    }
    assert ACTION_BY_CAPABILITY["crm.deal.update"] == {
        "hubspot": "hubspot.update_deal",
        "salesforce": "salesforce.update_opportunity",
    }
    assert ACTION_BY_CAPABILITY["crm.deal.get"] == {
        "hubspot": "hubspot.get_deal",
        "salesforce": "salesforce.get_opportunity",
    }
    assert ACTION_BY_CAPABILITY["crm.deal.search"] == {
        "hubspot": "hubspot.search_deals",
        "salesforce": "salesforce.search_opportunities",
    }


def test_hubspot_and_salesforce_create_mappings() -> None:
    hs = map_deal_capability_input(
        "crm.deal.create",
        "hubspot",
        {
            "deal": {
                "name": "Enterprise Renewal",
                "amount": 15000.5,
                "close_date": "2026-09-30",
                "pipeline": "sales",
                "stage": "qualified",
            }
        },
        _HS_CONFIG,
    )
    assert isinstance(hs, dict)
    assert hs["properties"] == {
        "dealname": "Enterprise Renewal",
        "amount": 15000.5,
        "closedate": "2026-09-30",
        "pipeline": "default",
        "dealstage": "appointmentscheduled",
    }
    sf = map_deal_capability_input(
        "crm.deal.create",
        "salesforce",
        {
            "deal": {
                "name": "Enterprise Renewal",
                "amount": 15000,
                "close_date": "2026-09-30",
                "stage": "qualified",
            }
        },
        _SF_CONFIG,
    )
    assert isinstance(sf, dict)
    assert sf["fields"] == {
        "Name": "Enterprise Renewal",
        "Amount": 15000,
        "CloseDate": "2026-09-30",
        "StageName": "Prospecting",
    }
    assert "pipeline" not in sf["fields"]
    assert "RecordTypeId" not in sf["fields"]


def test_salesforce_pipeline_is_unsupported() -> None:
    mapped = map_deal_capability_input(
        "crm.deal.create",
        "salesforce",
        {"deal": {"name": "Renewal", "pipeline": "default"}},
    )
    assert mapped == "crm_pipeline_unsupported"


def test_update_preserves_omitted_vs_null_and_object_ref() -> None:
    hs = map_deal_capability_input(
        "crm.deal.update",
        "hubspot",
        {
            "deal": {"object_type": "deal", "external_id": "99"},
            "changes": {"stage": None, "name": "Renewal"},
        },
    )
    assert isinstance(hs, dict)
    assert hs["deal_id"] == "99"
    assert hs["properties"]["dealstage"] is None
    assert hs["properties"]["dealname"] == "Renewal"
    assert "amount" not in hs["properties"]
    assert "pipeline" not in hs["properties"]
    wrong_type = resolve_crm_deal(
        capability="crm.deal.update",
        payload={
            "deal": {"object_type": "company", "external_id": "99"},
            "changes": {"name": "Renewal"},
        },
        connections=[_crm("hubspot")],
        enabled_capabilities=_CAPS,
    )
    assert wrong_type.reason_code == "crm_validation_failed"


def test_property_collision_is_rejected() -> None:
    mapped = map_deal_capability_input(
        "crm.deal.create",
        "hubspot",
        {"deal": {"name": "Enterprise Renewal", "properties": {"name": "Other"}}},
    )
    assert mapped == "crm_property_invalid"


def test_resolver_reuses_family_rules() -> None:
    unbound = resolve_crm_deal(
        capability="crm.deal.create",
        payload={"deal": {"name": "Renewal"}},
        connections=[_crm("hubspot", execution_domain="P")],
        enabled_capabilities=_CAPS,
    )
    assert unbound.reason_code == "crm_unbound"
    two = resolve_crm_deal(
        capability="crm.deal.create",
        payload={"deal": {"name": "Renewal"}},
        connections=[_crm("hubspot"), _crm("hubspot")],
        enabled_capabilities=_CAPS,
        provider_hint="hubspot",
    )
    assert two.reason_code == "binding_ambiguous"
    mixed = resolve_crm_deal(
        capability="crm.deal.update",
        payload={
            "deal": {"object_type": "deal", "external_id": "1"},
            "changes": {"name": "Renewal"},
        },
        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_opportunity"


def test_authorization_is_separate_from_eligibility() -> None:
    resolution = resolve_crm_deal(
        capability="crm.deal.create",
        payload={"deal": {"name": "Renewal"}},
        connections=[_crm("hubspot")],
        enabled_capabilities=_CAPS,
    )
    assert resolution.ok
    denied = dispatch_crm_deal_plan(
        resolution.plan,
        DispatchAuthorization(
            allowed=False,
            reason_code="crm_permission_denied",
            message="execution not authorized",
        ),
        diagnostics=resolution.diagnostics,
    )
    assert denied.ok is False
    assert denied.reason_code == "crm_permission_denied"


def test_queued_does_not_fabricate_deal_ref() -> None:
    resolution = resolve_crm_deal(
        capability="crm.deal.create",
        payload={"deal": {"name": "Renewal"}},
        connections=[_crm("hubspot")],
        enabled_capabilities=_CAPS,
    )
    public = to_public_crm_deal_result(
        resolution,
        capability="crm.deal.create",
        enqueue={"ok": True, "job_id": "job_1", "status": "queued"},
    ).as_dict()
    assert public == {"capability": "crm.deal.create", "status": "queued"}
    stripped = strip_capability_response(
        {**public, "deal_id": "123", "opportunity_id": "006xx", "job_id": "job_1"}
    )
    assert stripped == public


def test_hubspot_result_normalizes_to_crm_deal() -> None:
    resolution = resolve_crm_deal(
        capability="crm.deal.create",
        payload={"deal": {"name": "Renewal"}},
        connections=[_crm("hubspot", config=_HS_CONFIG)],
        enabled_capabilities=_CAPS,
    )
    public = to_public_crm_deal_result(
        resolution,
        capability="crm.deal.create",
        enqueue={
            "ok": True,
            "result": {
                "id": "123",
                "properties": {
                    "dealname": "Renewal",
                    "amount": "15000.5",
                    "closedate": 1759190400000,
                    "pipeline": "default",
                    "dealstage": "appointmentscheduled",
                },
            },
        },
    )
    assert public.status == "succeeded"
    assert public.deal == {
        "ref": {"object_type": "deal", "external_id": "123"},
        "name": "Renewal",
        "amount": 15000.5,
        "close_date": "2025-09-30",
        "pipeline": "sales",
        "stage": "qualified",
    }


def test_salesforce_result_normalizes_to_crm_deal() -> None:
    resolution = resolve_crm_deal(
        capability="crm.deal.update",
        payload={
            "deal": {"object_type": "deal", "external_id": "006xx"},
            "changes": {"name": "Renewal"},
        },
        connections=[_crm("salesforce", config=_SF_CONFIG)],
        enabled_capabilities=_CAPS,
    )
    public = to_public_crm_deal_result(
        resolution,
        capability="crm.deal.update",
        enqueue={
            "ok": True,
            "result": {
                "Id": "006xx",
                "Name": "Renewal",
                "Amount": 15000,
                "CloseDate": "2026-09-30",
                "StageName": "Prospecting",
            },
        },
    )
    assert public.status == "succeeded"
    assert public.deal == {
        "ref": {"object_type": "deal", "external_id": "006xx"},
        "name": "Renewal",
        "amount": 15000,
        "close_date": "2026-09-30",
        "stage": "qualified",
    }
    assert "pipeline" not in public.deal
    assert "currency" not in public.deal
