"""Architecture Lane Reporting production-path planner smoke.

Does not invent a Reporting recipe family; composition is deliberately held.
"""

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.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/reporting_freeze.receipt.txt"

GATED = (
    "payments.checkout",
    "membership.portal",
)

SMOKE = (
    ("Build a saved report dashboard for our staff.", None, ("reporting.dashboard",)),
    ("Staff need a reporting dashboard.", None, ("reporting.dashboard",)),
    ("Build a report definition summarizing customer invoices.", None, ("reporting.dashboard",)),
)

CONTROLS = (
    ("Staff manage invoices. No reports or dashboards.", None, ("billing.invoice",)),
    ("Staff manage a product catalog. No checkout, orders, or billing.", None, ("catalog.product",)),
)

NEGATIVES = (
    ("Do not add reporting.", None, "reporting.dashboard"),
    ("No dashboards needed.", None, "reporting.dashboard"),
    ("We use Tableau for that already.", None, "reporting.dashboard"),
    ("Power BI handles our analytics.", None, "reporting.dashboard"),
)


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 = []
    live = {recipe.id for recipe in load_recipes(composition_ready_only=True)}
    on_disk_reporting = [
        recipe.id
        for catalog in load_recipe_catalogs()
        for recipe in catalog.recipes
        if catalog.batch != "marketing_coverage"
        and "reporting.dashboard" in recipe.required_app_blocks
    ]
    for prompt, expected, required in SMOKE:
        recipe = _recipe(prompt)
        ids = _ids(prompt)
        matched = None if recipe is None else recipe.id
        ok = set(required) <= ids and matched == expected
        ok = ok and not (ids & set(GATED))
        rows.append({"prompt": prompt, "kind": "smoke", "matched": matched, "ids": sorted(ids), "pass": ok})
        if not ok:
            failures.append(prompt)
    for prompt, expected, required in CONTROLS:
        recipe = _recipe(prompt)
        ids = _ids(prompt)
        matched = None if recipe is None else recipe.id
        ok = matched == expected and set(required) <= ids
        ok = ok and "reporting.dashboard" not in ids
        ok = ok and not (ids & set(GATED))
        rows.append({"prompt": prompt, "kind": "control", "matched": matched, "ids": sorted(ids), "pass": ok})
        if not ok:
            failures.append(prompt)
    for prompt, expected, stripped in NEGATIVES:
        recipe = _recipe(prompt)
        ids = _ids(prompt)
        matched = None if recipe is None else recipe.id
        ok = matched == expected and stripped not in ids
        rows.append({"prompt": prompt, "kind": "negative", "matched": matched, "ids": sorted(ids), "pass": ok})
        if not ok:
            failures.append(prompt)
    payload = {
        "generated_at": datetime.now(UTC).isoformat(),
        "live_recipes": len(live),
        "on_disk_reporting_recipes": on_disk_reporting,
        "failures": failures,
        "pass": not failures and on_disk_reporting == [],
        "rows": rows,
    }
    if on_disk_reporting:
        payload["failures"] = [*failures, "on_disk_reporting_recipes"]
        payload["pass"] = False
    return payload


def main() -> int:
    payload = run_smoke()
    print(json.dumps({k: payload[k] for k in payload if k != "rows"}, indent=2))
    for row in payload["rows"]:
        mark = "PASS" if row["pass"] else "FAIL"
        print(f"{mark} {row['kind']:8} {row['prompt']!r} matched={row.get('matched')} ids={row['ids']}")
    if RECEIPT.is_file() and payload["pass"]:
        text = RECEIPT.read_text(encoding="utf-8")
        if "production_proven=pending_this_slice" in text:
            RECEIPT.write_text(
                text.replace("production_proven=pending_this_slice", "production_proven=local_smoke_pass"),
                encoding="utf-8",
            )
    return 0 if payload["pass"] else 1


if __name__ == "__main__":
    raise SystemExit(main())
