"""Phase 11D7E: generated-app file UX is provider-neutral over file_id."""

from __future__ import annotations

from pathlib import Path

from src.domain.codegen.file_adapter import file_adapter_files
from src.domain.starter_library.catalog import known_contract_ids
from src.domain.starter_library.record_form import canonical_file_id, merge_submit_values, plan_record_form_fields

REPO = Path(__file__).resolve().parents[1]
STARTERS = {
    "nuxt": REPO / "boilerplates" / "nuxt_app",
    "html": REPO / "boilerplates" / "html",
    "react": REPO / "boilerplates" / "react_app",
}
FILE_SURFACES = [
    REPO / "boilerplates/nuxt_app/components/starter/FileUpload.vue",
    REPO / "boilerplates/nuxt_app/components/starter/AttachmentList.vue",
    REPO / "boilerplates/nuxt_app/components/starter/StandardForm.vue",
    REPO / "boilerplates/nuxt_app/components/starter/blocks/AdminRecordDetail.vue",
    REPO / "boilerplates/react_app/src/components/starter/FileUpload.jsx",
    REPO / "boilerplates/react_app/src/components/starter/AttachmentList.jsx",
    REPO / "boilerplates/react_app/src/components/starter/library.jsx",
]
_PROVIDER_LEAKS = (
    "artifacts",
    "amazon_s3",
    "cloudflare_r2",
    "storage.presign_upload",
    "storage.file.put",
    "object_key",
    "connection_id",
    "bucket_name",
    "DocumentsFileUploader",
    "R2Uploader",
    "S3Uploader",
)


def test_starter_contracts_include_application_file_port():
    assert "file.upload" in known_contract_ids()
    assert "file.attachments" in known_contract_ids()
    assert "adapter.files" in known_contract_ids()
    for folder in STARTERS.values():
        contracts = {
            item["id"]: item["implementation"]
            for item in __import__("json").loads((folder / "p2hs" / "starter-contracts.json").read_text(encoding="utf-8"))[
                "contracts"
            ]
        }
        assert contracts["file.upload"]
        assert contracts["file.attachments"]
        assert contracts["adapter.files"]


def test_file_field_planner_stores_only_file_id():
    schema = {
        "fields": [
            {"key": "title", "name": "Title", "type": "text", "required": True},
            {"key": "passport", "name": "Passport", "type": "file", "required": True},
        ]
    }
    plan = plan_record_form_fields(schema)
    assert [field["key"] for field in plan["visible"]] == ["title", "passport"]
    assert plan["visible"][1]["type"] == "file"
    payload = merge_submit_values(
        schema,
        {
            "title": "Student",
            "passport": {
                "file_id": "file_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                "object_key": "evil/key",
                "connection_id": "conn_x",
            },
        },
    )
    assert payload == {"title": "Student", "passport": "file_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
    assert canonical_file_id("not-a-file") == ""
    assert canonical_file_id({"object_key": "x"}) == ""


def test_file_adapter_is_installed_for_pages_starters():
    nuxt = file_adapter_files("nuxt_app")
    html = file_adapter_files("html")
    assert "server/api/files/[...path].ts" in nuxt
    assert "server/api/files/index.post.ts" in nuxt
    assert "functions/api/files.js" in html
    assert "filesRequest" in html["functions/api/files.js"]
    assert 'from "../_lib/p2hs-files.mjs"' in html["functions/api/files.js"]
    assert 'from "../_lib/p2hs-records.mjs"' in html["functions/api/files.js"]
    assert "functions/api/files/[[path]].js" in html
    assert "p2hs-files" in nuxt["server/utils/p2hs-files.mjs"]
    blob = "\n".join(nuxt.values())
    assert "application-files" in blob
    assert "storage.file.put" not in blob
    assert "amazon_s3" not in blob


def test_generated_file_surfaces_are_provider_neutral():
    blob = "\n".join(path.read_text(encoding="utf-8") for path in FILE_SURFACES).lower()
    for leak in _PROVIDER_LEAKS:
        assert leak not in blob, leak
    client = (REPO / "src/domain/codegen/runtime/p2hs-app-client.js").read_text(encoding="utf-8")
    assert "uploadApplicationFile" in client
    assert "DocumentsFileUploader" not in blob


def test_generic_detail_hosts_attachments_without_document_branch():
    nuxt = (REPO / "boilerplates/nuxt_app/components/starter/AttachmentList.vue").read_text(encoding="utf-8")
    react = (REPO / "boilerplates/react_app/src/components/starter/AttachmentList.jsx").read_text(encoding="utf-8")
    for text in (nuxt, react):
        lowered = text.lower()
        assert 'entity-key="document"' not in lowered
        assert 'entitykey="document"' not in lowered
        assert "cloudflare" not in lowered
        assert "remove attachment" in lowered
        assert "attachfile" in lowered or "uploadapplicationfile" in lowered


def test_raw_storage_ports_remain_separate():
    catalog = (REPO / "src/integrations/contracts/platform-port-catalog.json").read_text(encoding="utf-8")
    assert '"port_id": "storage.presign_upload"' in catalog
    files = (REPO / "src/domain/codegen/runtime/p2hs-files.mjs").read_text(encoding="utf-8")
    assert "storage/:bucket" not in files
    assert "adapter.storage" not in files
