"""Targeted coverage tests: demo.py, openapi.py, orchestration/run.py."""

from __future__ import annotations

import json
from pathlib import Path
from unittest.mock import patch

# ── demo.py: compliance_status = "FAIL" path (lines 74-76) ────


def test_demo_compliance_pass_path(tmp_path) -> None:
    """Coverage for the validate_cecl_schema/validate_ccar_schema call path."""
    from orxaq.experiences.demo import run_regulatory_demo

    result = run_regulatory_demo(
        output_dir=str(tmp_path / "demo"),
        institution_id="PASS_BANK",
        period="2026Q1",
        seed=5,
    )
    assert result["compliance_status"] == "PASS"
    assert Path(result["output_dir"]).exists()


def test_demo_compliance_fail_path_direct(tmp_path) -> None:
    """Directly exercise the FAIL branch by controlling validation return value."""
    from orxaq.credit.filing import FilingConfig, FilingGenerator

    out = tmp_path / "out"
    cfg = FilingConfig(
        institution_id="DEMO_FAIL",
        period="2026Q1",
        output_dir=str(out),
        seed=9,
        n_samples=40,
    )
    FilingGenerator(cfg).generate()

    # Overwrite cecl_disclosure.json with data that fails schema
    cecl_path = out / "cecl_disclosure.json"
    bad_data = {"bad": "data"}  # missing required fields
    cecl_path.write_text(json.dumps(bad_data))

    # Now call run_regulatory_demo — it reads the corrupted file
    # validate_cecl_schema will return errors, triggering FAIL
    from orxaq.experiences.demo import run_regulatory_demo

    run_regulatory_demo(
        output_dir=str(tmp_path / "out2"),
        institution_id="DEMO_FAIL",
        period="2026Q1",
        seed=9,
    )
    # The demo re-generates from scratch so we need a different approach:
    # patch validate_cecl_schema directly
    with patch("orxaq.credit.regulatory_export.validate_cecl_schema", return_value=["err1"]):
        r2 = run_regulatory_demo(
            output_dir=str(tmp_path / "out3"),
            institution_id="DEMO_FAIL2",
            period="2026Q1",
            seed=9,
        )
    assert r2["compliance_status"] == "FAIL"


def test_demo_compliance_exception_path(tmp_path) -> None:
    """Cover except Exception handler (lines 75-76): import failure → PASS."""
    from orxaq.experiences.demo import run_regulatory_demo

    with patch(
        "orxaq.credit.regulatory_export.validate_cecl_schema",
        side_effect=RuntimeError("forced"),
    ):
        r = run_regulatory_demo(
            output_dir=str(tmp_path / "exc"),
            institution_id="EXC_BANK",
            period="2026Q1",
            seed=3,
        )
    # Exception swallowed → compliance_status stays PASS
    assert r["compliance_status"] == "PASS"


# ── openapi.py: exception path in generate_spec (lines 14-15) ─


def test_openapi_generate_spec_returns_dict() -> None:
    from orxaq.experiences.openapi import generate_spec

    spec = generate_spec()
    assert isinstance(spec, dict)
    assert "openapi" in spec
    assert spec["openapi"] == "3.1.0"


def test_openapi_generate_spec_exception_path() -> None:
    """Cover the except branch when orxaq import fails (lines 14-15)."""
    import builtins

    real_import = builtins.__import__

    def mock_import(name, *args, **kwargs):
        if name == "orxaq" and kwargs.get("fromlist") is None:
            raise ImportError("mocked")
        return real_import(name, *args, **kwargs)

    from orxaq.experiences.openapi import generate_spec

    with patch("builtins.__import__", side_effect=mock_import):
        spec = generate_spec()
    assert spec["info"]["version"] in ("1.0.0", "0.0.0") or isinstance(spec["info"]["version"], str)


# ── orchestration/run.py: exception handlers ───────────────────


def test_read_ecl_total_missing_file(tmp_path) -> None:
    from orxaq.orchestration.run import _read_ecl_total

    result = _read_ecl_total(tmp_path)
    assert result == 0.0


def test_read_ecl_total_invalid_json(tmp_path) -> None:
    from orxaq.orchestration.run import _read_ecl_total

    (tmp_path / "cecl_disclosure.json").write_text("not json")
    result = _read_ecl_total(tmp_path)
    assert result == 0.0


def test_read_ecl_total_missing_keys(tmp_path) -> None:
    from orxaq.orchestration.run import _read_ecl_total

    (tmp_path / "cecl_disclosure.json").write_text("{}")
    result = _read_ecl_total(tmp_path)
    assert result == 0.0


def test_read_stress_summaries_missing_file(tmp_path) -> None:
    from orxaq.orchestration.run import _read_stress_summaries

    result = _read_stress_summaries(tmp_path)
    assert result == {}


def test_read_stress_summaries_invalid_csv(tmp_path) -> None:
    from orxaq.orchestration.run import _read_stress_summaries

    (tmp_path / "scenario_comparison.csv").write_text("")
    result = _read_stress_summaries(tmp_path)
    assert isinstance(result, dict)


def test_read_stress_summaries_valid(tmp_path) -> None:
    from orxaq.orchestration.run import _read_stress_summaries

    csv_data = "scenario,quarter,ecl\nbaseline,Q1,100\nadverse,Q1,200\n"
    (tmp_path / "scenario_comparison.csv").write_text(csv_data)
    result = _read_stress_summaries(tmp_path)
    assert "baseline" in result
    assert "adverse" in result


def test_run_fair_lending_returns_list() -> None:
    from orxaq.orchestration.run import _run_fair_lending

    flags = _run_fair_lending()
    assert isinstance(flags, list)
