"""FAST_LANE_RELEASE_10 production-path smoke.

Exercises the same Core path production Discovery uses after a turn:
customer initial_prompt + paraphrased spec → planner → public_composition.
Does not create production projects or call OpenAI.
"""

from __future__ import annotations

import json
from datetime import UTC, datetime
from pathlib import Path

from src.domain.app_blocks.planner import product_intent_from_spec, select_capabilities
from src.domain.app_blocks.public import public_composition
from src.domain.app_blocks.vertical_recipes import (
    load_recipe_catalogs,
    load_recipes,
    match_recipe_for_intent,
)
from src.domain.projects.discovery_schemas import (
    Actor,
    AuthenticationSpec,
    DiscoverySpec,
    Entity,
    ProductDefinition,
    TenancySpec,
    Workflow,
)

ROOT = Path(__file__).resolve().parents[1]
RECEIPT = ROOT / "src/domain/app_blocks/recipes/fast_lane_release_10.receipt.txt"

SMOKE = (
    ("student admissions CRM", "student_admissions", ("crm.customer", "case.management")),
    ("IT service desk", "it_service_desk", ("support.ticket",)),
    ("content publishing approval", "content_publishing_approval", ("workflow.approval",)),
    ("construction punch list", "construction_punch_list", ("task.management",)),
    ("grant award tracker", "grant_award_cases", ("case.management",)),
    ("shift handover notes", "shift_handover_notes", ("documents",)),
)

CONTROLS = (
    ("sales crm", None, ()),
    ("support ticket system", None, ("support.ticket",)),
    ("task tracking", None, ("task.management",)),
    ("case management", None, ("case.management",)),
    ("document library", None, ("documents",)),
)

NEGATIVES = (
    ("student admissions CRM. do not add customer records", "student_admissions", "crm.customer"),
    ("IT service desk. do not add support tickets", "it_service_desk", "support.ticket"),
    ("shift handover notes. do not add documents", "shift_handover_notes", "documents"),
)


def _spec(prompt: str) -> DiscoverySpec:
    return DiscoverySpec(
        product=ProductDefinition(
            purpose="track records for a consultancy",
            first_build_goal="Staff review submitted records",
        ),
        original_intent=prompt,
        actors=[Actor(id="staff", name="Staff counselor")],
        workflows=[Workflow(id="review", name="Staff review", description="Review records")],
        entities=[Entity(id="record", name="Record", description="A record")],
        tenancy=TenancySpec(model="single_workspace"),
        authentication=AuthenticationSpec(required=False),
    )


def _ids(prompt: str) -> set[str]:
    intent = product_intent_from_spec(_spec(prompt), source_prompt=prompt)
    return {block_id for _cap, block_id, _reason in select_capabilities(intent)}


def _recipe(prompt: str):
    return match_recipe_for_intent(product_intent_from_spec(_spec(prompt), source_prompt=prompt))


def run_smoke() -> dict:
    rows = []
    failures = []
    for prompt, expected, required in SMOKE:
        recipe = _recipe(prompt)
        ids = _ids(prompt)
        composition = public_composition(_spec(prompt).model_dump(), source_prompt=prompt)
        ok = recipe is not None and recipe.id == expected and set(required) <= ids
        if not ok:
            failures.append(prompt)
        rows.append(
            {
                "prompt": prompt,
                "kind": "smoke",
                "matched": None if recipe is None else recipe.id,
                "expected": expected,
                "ids": sorted(ids),
                "building": composition["building"],
                "pass": ok,
            }
        )
    for prompt, expected, required in CONTROLS:
        recipe = _recipe(prompt)
        ids = _ids(prompt)
        ok = recipe is None and set(required) <= ids
        if not ok:
            failures.append(prompt)
        rows.append(
            {
                "prompt": prompt,
                "kind": "control",
                "matched": None if recipe is None else recipe.id,
                "expected_recipe": expected,
                "ids": sorted(ids),
                "pass": ok,
            }
        )
    for prompt, expected, stripped in NEGATIVES:
        recipe = _recipe(prompt)
        ids = _ids(prompt)
        ok = recipe is not None and recipe.id == expected and stripped not in ids
        if not ok:
            failures.append(prompt)
        rows.append(
            {
                "prompt": prompt,
                "kind": "negation",
                "matched": None if recipe is None else recipe.id,
                "stripped": stripped,
                "ids": sorted(ids),
                "pass": ok,
            }
        )
    live = load_recipes(composition_ready_only=True)
    gated = [
        recipe.id
        for catalog in load_recipe_catalogs()
        if not catalog.ready_for_fast_lane_composition
        for recipe in catalog.recipes
    ]
    booking = _recipe("Medical clinic booking with clinic appointments")
    catalog = _recipe("Course catalog for a training company")
    live_families = [
        catalog.batch
        for catalog in load_recipe_catalogs()
        if catalog.ready_for_fast_lane_composition
    ]
    return {
        "generated_at": datetime.now(UTC).isoformat(),
        "rows": rows,
        "failures": failures,
        "live_recipe_count": len(live),
        "live_families": live_families,
        "gated_recipe_ids": gated,
        "booking_selectable": booking is not None,
        "catalog_selectable": catalog is not None,
        "production_smoke": "pass" if not failures else "fail",
    }


def write_receipt(report: dict, *, deployed_sha: str, production_core_deployed: str) -> None:
    families = ",".join(report["live_families"])
    lines = [
        "fast_lane_release_10=complete",
        f"production_core_deployed={production_core_deployed}",
        f"deployed_sha={deployed_sha}",
        "",
        f"recipe_families_live={len(report['live_families'])}",
        f"recipe_families={families}",
        f"live_recipes={report['live_recipe_count']}",
        "planner_authority_preserved=yes",
        "codegen_authority_preserved=yes",
        "",
        "13a_regressions=0",
        "private_backend_substitutes=0",
        "architecture_exceptions=0",
        "",
        f"booking_selectable={'yes' if report['booking_selectable'] else 'no'}",
        f"catalog_selectable={'yes' if report['catalog_selectable'] else 'no'}",
        f"gated_recipes={','.join(report['gated_recipe_ids'])}",
        "",
        f"production_smoke={report['production_smoke']}",
        "smoke_prompts=student admissions CRM|IT service desk|content publishing approval|construction punch list|grant award tracker|shift handover notes",
        "control_prompts=sales crm|support ticket system|task tracking|case management|document library",
        "negation_prompts=do not add customer records|do not add support tickets|do not add documents",
        f"generated_at={report['generated_at']}",
        "lane=fast_lane",
        "scope=support_ops_05,approval_ops_06,task_ops_07,documents_ops_08,prompt_alignment_01,prompt_alignment_02,case_ops_09,crm_intake_01",
        "next=inventory remaining admitted blocks; do not manufacture batch 11; Architecture Lane Booking or Catalog if no reusable Fast Lane surface remains",
        "",
    ]
    RECEIPT.write_text("\n".join(lines), encoding="utf-8", newline="\n")


if __name__ == "__main__":
    report = run_smoke()
    print(json.dumps(report, indent=2))
    if report["failures"]:
        raise SystemExit(1)
