"""Test e2e del LAND-simplified pipeline con escenario Vero Beach $7K.

Verifica:
1. detect_property_type_anomalies dispara should_bypass=True
2. analyze_deal route a _analyze_land_simplified
3. NO se ejecutan DealAnalyzer/LenderMatcher/ValueEstimator/OfferStrategist
4. NO se computa Cap Rate / DSCR (computed_scenarios queda {})
5. Briefing arranca con "🚨 ALERTA CRITICA: PROPIEDAD TIPO TERRENO DETECTADA"
6. Pipeline mode = land_simplified
"""
from __future__ import annotations
import io, sys, time
from pathlib import Path

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))

from orchestrator import DealInputs, BuyerProfile, analyze_deal  # noqa: E402


def main() -> int:
    print("=" * 70)
    print("LAND bugfix test — Vero Beach $7K (user mistakenly declared SFR)")
    print("=" * 70)

    deal = DealInputs(
        address="5800 32nd Ave, Vero Beach, FL 32966",
        price=7_000,
        rent=0,
        property_tax=200,
        insurance=0,
        hoa=0,
        sqft=0,
        beds=0,
        baths=0,
        year_built=0,
        arv=0,
        property_type="sfr",  # USER MISTAKENLY DECLARED SFR
        listing_description="0.23 acre buildable lot, ready for construction. Cleared and graded.",
    )
    profile = BuyerProfile(
        profile_class="C",
        fico=720,
        capital_available=50_000,
    )

    print(f"DEAL: {deal.address}")
    print(f"  price=${deal.price:,} | property_type DECLARED='{deal.property_type}'")
    print(f"  year_built={deal.year_built}, sqft={deal.sqft}, beds/baths={deal.beds}/{deal.baths}")
    print(f"  rent={deal.rent}, arv={deal.arv}")
    print(f"  description: {deal.listing_description}")
    print()

    def log(msg):
        print(f"  [{time.strftime('%H:%M:%S')}] {msg}")

    t0 = time.perf_counter()
    result = analyze_deal(deal, profile, photo_bytes=None, status_cb=log)
    elapsed = time.perf_counter() - t0

    print()
    print("=" * 70)
    print(f"PIPELINE COMPLETED in {elapsed:.0f}s")
    print("=" * 70)

    # ─── Validaciones ──────────────────────────────────────────────────────
    ptw = result.property_type_warning or {}
    mode = result.pipeline_mode

    print()
    print("VALIDATIONS:")
    print(f"  pipeline_mode: {mode}")
    assert mode == "land_simplified", f"FAIL: expected land_simplified, got {mode}"
    print("    ✅ pipeline_mode == 'land_simplified'")

    print(f"  warnings detectados: {len(ptw.get('warnings', []))}")
    assert len(ptw.get("warnings", [])) >= 4, f"FAIL: expected >=4 warnings"
    print("    ✅ >= 4 warnings dispararon detection")

    print(f"  should_bypass_sfr_pipeline: {ptw.get('should_bypass_sfr_pipeline')}")
    assert ptw.get("should_bypass_sfr_pipeline") is True
    print("    ✅ should_bypass=True")

    # SFR agents should be SKIPPED
    da_out = (result.deal_analysis or {}).get("output", "")
    le_out = (result.lender or {}).get("output", "")
    ve_out = (result.value_estimate or {}).get("output", "")
    os_out = (result.offer_strategy or {}).get("output", "")
    print(f"  DealAnalyzer output (should be SKIPPED): {da_out[:80]!r}")
    print(f"  LenderMatcher output (should be SKIPPED): {le_out[:80]!r}")
    print(f"  ValueEstimator output (should be SKIPPED): {ve_out[:80]!r}")
    print(f"  OfferStrategist output (should be SKIPPED): {os_out[:80]!r}")
    assert "SKIPPED" in da_out and "land" in da_out.lower()
    assert "SKIPPED" in le_out
    assert "SKIPPED" in ve_out
    assert "SKIPPED" in os_out
    print("    ✅ Los 4 agentes SFR-specific NO se ejecutaron (SKIPPED)")

    # computed_scenarios should be empty (no DSCR/Cap Rate)
    cs = result.computed_scenarios or {}
    print(f"  computed_scenarios (should be empty for LAND): {len(cs)} keys")
    assert cs == {}, f"FAIL: computed_scenarios should be empty for LAND, got: {cs}"
    print("    ✅ NO se computó finance_calculator (no hay Cap Rate / DSCR inflado)")

    # Briefing should start with land warning
    briefing_out = (result.executive_briefing or {}).get("output", "")
    print(f"\n  Briefing first 300 chars:")
    print(f"  {briefing_out[:300]}")
    briefing_lower = briefing_out.lower()
    has_alert = any(kw in briefing_lower for kw in [
        "alerta", "terreno", "land", "propiedad tipo terreno",
    ])
    assert has_alert, "FAIL: briefing missing LAND alert"
    print()
    print("    ✅ Briefing destaca alerta LAND")

    # Coordinator output should NOT have DSCR/Cap Rate inflados
    coord_out = (result.final or {}).get("output", "")
    coord_lower = coord_out.lower()
    has_dscr = "dscr" in coord_lower
    has_caprate = "cap rate" in coord_lower
    has_coc = "coc" in coord_lower or "cash on cash" in coord_lower
    print(f"  Coordinator mentions DSCR: {has_dscr}")
    print(f"  Coordinator mentions Cap Rate: {has_caprate}")
    print(f"  Coordinator mentions CoC: {has_coc}")
    # Es OK que el LLM las mencione para EXPLICAR que no aplican, pero NO debe presentarlas
    # como metricas calculadas. Validamos que mencione "no aplica" o "land" si las menciona.
    if has_dscr or has_caprate or has_coc:
        explains_inapplicable = any(kw in coord_lower for kw in [
            "no aplica", "no apply", "land", "terreno", "no se calcul",
        ])
        if explains_inapplicable:
            print("    ✅ Coordinator menciona metricas SFR pero CLARIFICA que no aplican")
        else:
            print("    ⚠️ Coordinator menciona DSCR/Cap Rate sin clarificar — review")

    print()
    print("=" * 70)
    print("✅ ALL VALIDATIONS PASSED — LAND bug FIXED")
    print("=" * 70)

    # Save the result for inspection
    print(f"\nFull result saved by orchestrator. Check analyses/*_LAND.json")
    return 0


if __name__ == "__main__":
    sys.exit(main())
