"""Phase 2B — document.* contract freeze. Mapping only; not invocable."""
from __future__ import annotations

from src.domain.codegen.platform_backend import _compact_connectors
from src.domain.codegen.prompt_wrapper import (
    _P2HS_CLOUD_CONTRACT,
    _P2HS_CORE_API_GUIDANCE,
    _app_recipes,
)
from src.domain.connectors.catalog import CONNECTORS, get_action, slugs_implementing
from src.domain.connectors.invoke_capabilities import (
    CAPABILITY_CONVERSION_PATTERN,
    DOCUMENT_APPEND_TEXT_INPUT_SCHEMA,
    DOCUMENT_CREATE_INPUT_SCHEMA,
    DOCUMENT_FAMILY_PHASE_2A,
    DOCUMENT_FAMILY_PHASE_2B,
    DOCUMENT_FAMILY_WORKING_MODEL,
    DOCUMENT_FROZEN_VERBS,
    DOCUMENT_GET_INPUT_SCHEMA,
    DOCUMENT_HYPOTHESIZED_VERBS_NOT_FROZEN,
    DOCUMENT_INSERT_TEXT_INPUT_SCHEMA,
    DOCUMENT_LIVE_PATH_AUDIT,
    DOCUMENT_REPLACE_TEXT_INPUT_SCHEMA,
    DOCUMENT_VERB_CLASSIFICATION,
    GOOGLE_DOCS_DOCUMENT_MAPPING,
    GOOGLE_DOCS_INSERT_TEXT_MAPPING,
    GOOGLE_DOCS_REPLACE_TEXT_MAPPING,
    INVOKE_CAPABILITIES,
    is_implemented,
)
from src.domain.connectors.public_gateway import (
    PHASE_2A_STATUS,
    PHASE_2B_STATUS,
    PHASE_2C_STATUS,
    PHASE_2D_STATUS,
    PHASE_2E_STATUS,
    PHASE_2F_STATUS,
    PHASE_2G_STATUS,
    PHASE_2P_STATUS,
    PHASE_3_STATUS,
    PHASE_4_STATUS,
    PUBLIC_INVOCABLE_CAPABILITIES,
    strip_capability_response,
)
from src.domain.manifest.service import _connectors_manifest_envelope


def test_phase_2b_freezes_document_contracts_without_runtime_flips() -> None:
    pattern = CAPABILITY_CONVERSION_PATTERN
    assert PHASE_2A_STATUS == "frozen"
    assert PHASE_2P_STATUS == "complete"
    assert PHASE_2B_STATUS == "frozen"
    assert PHASE_2C_STATUS == "complete"
    assert PHASE_2D_STATUS == "complete"
    assert PHASE_2E_STATUS == "complete"
    assert PHASE_2F_STATUS == "complete"
    assert PHASE_2G_STATUS == "complete"
    assert PHASE_3_STATUS == "complete"
    assert PHASE_4_STATUS == "complete"
    assert pattern["phase_2_status"] == "2g_codegen_defaults_complete"
    assert pattern["phase_2b_status"] == "frozen"
    assert pattern["phase_2c_status"] == "complete"
    assert pattern["phase_2d_status"] == "complete"
    assert pattern["phase_2e_status"] == "complete"
    assert pattern["phase_2f_status"] == "complete"
    assert pattern["phase_2g_status"] == "complete"
    assert pattern["phase_3_status"] == "complete"
    assert pattern["next_program_slice"] == "9_app_block_modernization"
    assert pattern["opened_families"]["document.*"] == "A"
    assert pattern["templates"]["document.create"] == "provider_backed_then_codegen_normalize"
    assert DOCUMENT_FAMILY_PHASE_2B["catalog_invocable"] is False
    assert DOCUMENT_FAMILY_PHASE_2B["implements_attached"] is False
    assert DOCUMENT_FAMILY_PHASE_2B["codegen_default"] is False
    assert DOCUMENT_FAMILY_PHASE_2B["resolver"] is False
    assert pattern["opened_families"]["spreadsheet.*"] == "A"
    assert "spreadsheet.*" not in pattern["closed_families"]


def test_live_google_docs_path_is_customer_bound_provider_only() -> None:
    assert "google_docs" in CONNECTORS
    connector = CONNECTORS["google_docs"]
    assert connector.auth_type == "oauth"
    audit = DOCUMENT_LIVE_PATH_AUDIT
    assert audit["execution_domain"] == "C"
    assert audit["core_catalog_connector"] == "google_docs"
    assert audit["p2hs_owned_google_path"] is False
    assert audit["codegen_default"] is True
    assert audit["implements"] == audit["core_catalog_actions"]
    assert GOOGLE_DOCS_DOCUMENT_MAPPING["status"] == "resolver_mapped"
    assert GOOGLE_DOCS_DOCUMENT_MAPPING["implements"] is True
    assert GOOGLE_DOCS_DOCUMENT_MAPPING["resolver_candidate"] is True
    for slug in audit["core_catalog_actions"]:
        pair = get_action(slug)
        assert pair is not None
        assert pair[1].implements != ()
        assert pair[1].required_capabilities == ("integrations.execute",)
    assert get_action("google_docs.export") is None
    for sibling in audit["sibling_google_connectors_not_docs"]:
        assert sibling in CONNECTORS


def test_five_document_verbs_are_frozen_template_a_not_invocable() -> None:
    assert DOCUMENT_VERB_CLASSIFICATION == {
        "document.create": "A",
        "document.get": "A",
        "document.insert_text": "A",
        "document.append_text": "A",
        "document.replace_text": "A",
    }
    assert DOCUMENT_FAMILY_PHASE_2A["classification"] == "audit"
    assert DOCUMENT_FAMILY_PHASE_2B["classification"] == "A"
    assert DOCUMENT_FAMILY_PHASE_2B["verbs_frozen"] == DOCUMENT_FROZEN_VERBS
    assert DOCUMENT_HYPOTHESIZED_VERBS_NOT_FROZEN == ("document.export",)
    assert "document.export" not in INVOKE_CAPABILITIES
    for verb in DOCUMENT_FROZEN_VERBS:
        spec = INVOKE_CAPABILITIES[verb]
        assert spec["status"] == "implemented"
        assert spec["method"] == f"POST /api/projects/{{project_id}}/capabilities/{verb}"
        assert is_implemented(verb) is True
        assert verb in PUBLIC_INVOCABLE_CAPABILITIES


def test_frozen_document_contracts_are_provider_neutral() -> None:
    assert set(DOCUMENT_CREATE_INPUT_SCHEMA["properties"]) == {"title", "metadata"}
    assert set(DOCUMENT_GET_INPUT_SCHEMA["required"]) == {"document"}
    assert set(DOCUMENT_INSERT_TEXT_INPUT_SCHEMA["required"]) == {"document", "text"}
    assert set(DOCUMENT_APPEND_TEXT_INPUT_SCHEMA["required"]) == {"document", "text"}
    assert set(DOCUMENT_REPLACE_TEXT_INPUT_SCHEMA["required"]) == {"document", "find"}
    position = DOCUMENT_INSERT_TEXT_INPUT_SCHEMA["properties"]["position"]
    assert position["enum"] == ["start"]
    assert position["default"] == "start"
    assert position["x-p2hs"]["not_google_index"] is True
    assert "index" not in DOCUMENT_INSERT_TEXT_INPUT_SCHEMA["properties"]
    assert "match_case" not in DOCUMENT_REPLACE_TEXT_INPUT_SCHEMA["properties"]
    assert "document_id" not in DOCUMENT_GET_INPUT_SCHEMA["properties"]
    assert GOOGLE_DOCS_INSERT_TEXT_MAPPING["unmapped_provider_fields"] == ("index", "document_id")
    assert GOOGLE_DOCS_REPLACE_TEXT_MAPPING["unmapped_provider_fields"] == (
        "match_case",
        "document_id",
    )
    assert GOOGLE_DOCS_INSERT_TEXT_MAPPING["position_map"] == {"start": 1}


def test_working_model_keeps_google_ids_behind_bindings() -> None:
    model = DOCUMENT_FAMILY_WORKING_MODEL
    assert model["resource"] == "logical_document_alias"
    assert model["provider_document_id"] == "connection_or_project_binding"
    assert model["no_giant_google_workspace_capability"] is True
    assert model["spreadsheet_family_closed"] is False
    assert model["unique_without_alias"] == "document_unbound"
    assert "first-wins" in model["multiple"]
    forbidden = set(model["not_in_generated_code"])
    assert {
        "document_id",
        "revision_id",
        "google_docs_api_method",
        "documents.batchUpdate",
    } <= forbidden


def test_phase_2b_does_not_expose_codegen_defaults() -> None:
    envelope = _connectors_manifest_envelope(items={})
    capabilities = envelope.get("capabilities") or {}
    for verb in DOCUMENT_FROZEN_VERBS:
        cap = capabilities[verb]
        assert cap["status"] == "implemented"
        assert cap["role"] == "default"
        assert cap["method"] is not None
        assert cap["implemented_by"] == list(slugs_implementing(verb))
    for verb in DOCUMENT_HYPOTHESIZED_VERBS_NOT_FROZEN:
        assert verb not in capabilities
    compact = _compact_connectors(envelope)
    for verb in DOCUMENT_FROZEN_VERBS:
        assert compact["capabilities"][verb]["status"] == "implemented"
        assert compact["capabilities"][verb]["role"] == "default"
    recipes = _app_recipes()
    assert "capabilities/document." in recipes
    assert "document.create" in _P2HS_CLOUD_CONTRACT
    assert "document.create" in _P2HS_CORE_API_GUIDANCE
    stripped = strip_capability_response(
        {
            "capability": "document.create",
            "document_id": "1abc",
            "revision_id": "3",
            "status": "queued",
        }
    )
    assert "document_id" not in stripped
    assert "revision_id" not in stripped
    assert stripped["status"] == "queued"
