"""Application experience is a projection of the reconciled GenerationPlan."""

import json
import tempfile

from src.domain.codegen.app_sdk import publish_experience_asset, staff_shell_files
from src.domain.codegen.application_experience import (
    compile_application_experience,
    published_experience,
)
from src.domain.codegen.composition_reconcile import _stored_plan_is_newer


def test_dental_prompt_shape_projects_clinic_modules_without_inventing_blocks():
    experience = compile_application_experience(
        domain="dental clinic",
        archetype_id=None,
        purpose="appointment booking and contact",
        app_block_ids=["forms.contact", "booking.appointment", "crm.customer"],
        feature_pack_ids=["contact-capture"],
        authentication_required=True,
    )
    assert experience.design.recipe == "clinic"
    assert [module.id for module in experience.admin_modules] == [
        "inbox",
        "customers",
        "bookings",
        "team",
    ]
    assert "catalog" not in experience.public_surfaces
    assert "contact" in experience.public_surfaces
    assert "booking" in experience.public_surfaces
    template_ids = [item.template_id for item in experience.notification_bindings]
    assert "contact_capture.confirmation.v1" in template_ids
    assert "auth.magic_link.v1" in template_ids
    assert all(
        not item.template_id.startswith("billing.")
        for item in experience.notification_bindings
    )


def test_baseline_blocks_are_marked_installed_not_dropped():
    experience = compile_application_experience(
        domain="studio",
        purpose="update the homepage copy",
        app_block_ids=["forms.contact", "booking.appointment"],
        feature_pack_ids=["contact-capture"],
        authentication_required=False,
        fresh_block_ids={"forms.contact"},
        baseline_block_ids={"forms.contact", "booking.appointment"},
    )
    sources = {item.id: item.source for item in experience.selection if item.kind == "app_block"}
    assert sources["forms.contact"] == "current_prompt"
    assert sources["booking.appointment"] == "installed_baseline"


def test_missing_or_incompatible_experience_publishes_no_modules():
    unavailable = published_experience(None)
    assert unavailable["experience_status"] == "unavailable"
    assert unavailable["admin_modules"] == []
    stale = {
        "schema_version": "experience.v0",
        "admin_modules": [
            {"id": "inbox", "label": "Inbox", "block_id": "forms.contact"},
        ],
    }
    assert published_experience(stale)["admin_modules"] == []
    ready = published_experience({
        "schema_version": "experience.v1",
        "admin_modules": [{
            "id": "bookings",
            "label": "Bookings",
            "audience": "staff",
            "block_id": "booking.appointment",
        }],
    })
    assert ready["experience_status"] == "ready"
    assert [item["id"] for item in ready["admin_modules"]] == ["bookings"]


def test_staff_shell_does_not_invent_an_inbox_without_a_plan():
    with tempfile.TemporaryDirectory() as repo_path:
        publish_experience_asset(repo_path, "html")
        files = staff_shell_files("html", repo_path)
        shell = files["admin.html"]
        asset_path = f"{repo_path}/p2hs-application-experience.json"
        asset = json.loads(open(asset_path, encoding="utf-8").read())
    assert asset["experience_status"] == "unavailable"
    assert asset["admin_modules"] == []
    assert "forms.contact" not in shell
    assert "./p2hs-application-experience.json" in shell
    assert "experience_status!==\"ready\"" in shell


def test_older_reconcile_does_not_replace_a_newer_plan():
    older = {"provenance": {"compiled_at": "2026-10-11T00:00:00"}}
    newer = {"provenance": {"compiled_at": "2026-10-11T01:00:00"}}
    assert _stored_plan_is_newer(newer, older) is True
    assert _stored_plan_is_newer(older, newer) is False
    assert _stored_plan_is_newer({}, newer) is False
