"""W18G background image smoke — 2 minimal safety tests.

1. dry-run caller never invokes the openai caller AND no PNG is written;
   fake generate mode writes a PNG via the monkeypatched caller and
   image_generation_count flips to 1.
2. target_bg_id outside the wave allowlist fails fast; methodology grep
   guards against scenario-specific tokens in the script source.
"""
from __future__ import annotations

import json
import re
import sys
from pathlib import Path


_REPO_ROOT = Path(__file__).resolve().parents[3]
_SCRIPTS_DIR = _REPO_ROOT / "backend" / "scripts"
if str(_SCRIPTS_DIR) not in sys.path:
    sys.path.insert(0, str(_SCRIPTS_DIR))


def _make_fake_w18f_run(tmp_path: Path, *, base_fp_png_exists: bool = True):
    """Build a minimal W18F-shaped run dir on tmp_path."""
    run_dir = tmp_path / "w18f_fake_run"
    run_dir.mkdir()
    base_fp_rel = "fp_l05_01_base.png"
    if base_fp_png_exists:
        png_dir = tmp_path / "fake_png"
        png_dir.mkdir(exist_ok=True)
        ref_png = png_dir / "fp.png"
        ref_png.write_bytes(b"\x89PNG\r\n\x1a\nfake")
        base_fp_path_str = str(ref_png)
    else:
        base_fp_path_str = "/non/existent.png"

    assembly = {
        "assembly_preview_by_bg": {
            "L05B04": {
                "bg_id": "L05B04", "fp_id": "fp_l05_01",
                "base_fp_ref_path": base_fp_path_str,
                "assembled_background_prompt_preview": (
                    "PROSE BODY HERE\n\n--- separator ---\n\n"
                    "APPENDIX BODY HERE referencing #3 #8 #12 #18 #19 #23"
                ),
                "transient_overlay_marker_numbers": [18, 19, 23],
                "clean_background_expected": False,
                "consumer_decision_preview": (
                    "READY_FOR_BACKGROUND_PROMPT_DRY_RUN"
                ),
            }
        },
        "fp_id": "fp_l05_01",
    }
    (run_dir / "background_prompt_region_ref_assembly_preview.json").write_text(
        json.dumps(assembly, ensure_ascii=False)
    )
    (run_dir / "run_meta.json").write_text(
        json.dumps({"run_id": "w18f_fake", "stage": "w18f"})
    )
    return run_dir, Path(base_fp_path_str)


def test_w18g_dry_run_skips_api_and_fake_generate_writes_png(tmp_path):
    """Dry-run: no openai call, no PNG, invariants reflect mode=dry_run.
    Fake --generate: monkeypatched caller is invoked, PNG written, all
    invariants PASS (production guards stay green)."""
    import experiment_background_image_smoke_from_region_ref_slice as mod

    w18f_dir, _ref = _make_fake_w18f_run(tmp_path)
    out_root = tmp_path / "w18g_out"

    # Sentinel: any accidental call to the caller in dry-run blows up.
    def _explode(**_kw):
        raise AssertionError("caller invoked in dry-run mode")

    orig = mod._openai_edit_caller
    mod._openai_edit_caller = _explode
    try:
        rc_dry = mod.main([
            "--derive-background-smoke-from", str(w18f_dir),
            "--target-bg-id", "L05B04",
            "--output-root", str(out_root),
        ])
    finally:
        mod._openai_edit_caller = orig
    assert rc_dry == 0, "dry-run should succeed without api call"

    # Find the dry-run dir.
    dry_dirs = sorted(out_root.iterdir())
    assert len(dry_dirs) == 1
    dry_meta = json.loads((dry_dirs[0] / "run_meta.json").read_text())
    assert dry_meta["mode"] == "dry_run"
    assert dry_meta["image_api_call_count"] == 0
    assert dry_meta["image_generation_count"] == 0
    assert not (dry_dirs[0] / "png" / "L05B04.png").exists()
    dry_report = json.loads(
        (dry_dirs[0] / "w18g_compatibility_report.json").read_text()
    )
    assert dry_report["all_pass"] is True, dry_report

    # Fake generate: monkeypatch the caller to write a small PNG.
    def _fake_edit(*, bg_id, prompt, model, size, base_fp_png_path,
                   target_path, client, **_kw):
        target_path.parent.mkdir(parents=True, exist_ok=True)
        target_path.write_bytes(b"\x89PNG\r\n\x1a\nfake-generated")
        return {
            "status": "success",
            "png_size_bytes": target_path.stat().st_size,
            "actual_api_response_meta": {"latency_ms": 1},
            "error_meta": {},
            "cost_meta": {"provider_usage": {"fake": True}},
        }

    class _FakeClient:
        pass

    def _fake_client():
        return _FakeClient()

    mod._openai_edit_caller = _fake_edit
    mod._create_openai_client = _fake_client  # type: ignore[attr-defined]
    # Set a fake OPENAI_API_KEY so the env gate passes.
    import os
    prev_key = os.environ.get("OPENAI_API_KEY")
    os.environ["OPENAI_API_KEY"] = "sk-fake-for-test"
    try:
        rc_gen = mod.main([
            "--derive-background-smoke-from", str(w18f_dir),
            "--target-bg-id", "L05B04",
            "--generate",
            "--model", "gpt-image-2",
            "--output-root", str(out_root),
        ])
    finally:
        mod._openai_edit_caller = orig
        if prev_key is None:
            os.environ.pop("OPENAI_API_KEY", None)
        else:
            os.environ["OPENAI_API_KEY"] = prev_key
    assert rc_gen == 0, "fake generate should succeed"

    gen_dirs = sorted(out_root.iterdir())
    assert len(gen_dirs) == 2
    gen_dir = [d for d in gen_dirs if d != dry_dirs[0]][0]
    gen_meta = json.loads((gen_dir / "run_meta.json").read_text())
    assert gen_meta["mode"] == "generated"
    assert gen_meta["image_api_call_count"] == 1
    assert gen_meta["image_generation_count"] == 1
    png_p = gen_dir / "png" / "L05B04.png"
    assert png_p.exists() and png_p.stat().st_size > 0
    gen_report = json.loads(
        (gen_dir / "w18g_compatibility_report.json").read_text()
    )
    assert gen_report["all_pass"] is True, gen_report


def test_w18g_target_bg_restriction_and_methodology_grep(tmp_path):
    """target_bg_id outside L05B04 wave lock fails fast. Script source
    must not embed scenario-specific tokens."""
    import experiment_background_image_smoke_from_region_ref_slice as mod

    w18f_dir, _ref = _make_fake_w18f_run(tmp_path)
    out_root = tmp_path / "w18g_out_bad"
    rc = mod.main([
        "--derive-background-smoke-from", str(w18f_dir),
        "--target-bg-id", "L05B99",
        "--output-root", str(out_root),
    ])
    assert rc == 1
    bad_dir = sorted(out_root.iterdir())[0]
    bad_meta = json.loads((bad_dir / "run_meta.json").read_text())
    assert "target_bg_outside_allowed" in bad_meta["failed_invariants"]

    script_path = (
        _SCRIPTS_DIR
        / "experiment_background_image_smoke_from_region_ref_slice.py"
    )
    assert script_path.exists()
    forbidden_tokens = [
        "b" + "edroom", "ki" + "tchen", "blood" + "stain", "cur" + "tain",
        "coo" + "ktop", "tele" + "vision", "cri" + "me", "vi" + "lla",
        "roo" + "ftop", "foot" + "print", "pol" + "ice", "de" + "ck",
        "wheel" + "house", "ba" + "throom", "su" + "ri-young",
    ]
    pat = re.compile(r"(?i)\b(" + "|".join(forbidden_tokens) + r")\b")
    m = pat.search(script_path.read_text())
    assert m is None, (
        f"{script_path.name}: scenario-specific token leaked → "
        f"{m.group(0) if m else ''}"
    )
