"""
Real, executed tests for app/core/config.py (StockLab final engineering pass, Part A7 follow-up).

Why this file exists: docs/TEST_REPORT.md previously claimed `pydantic`/`pydantic_settings` were
absent from this build environment, so the fail-closed production-safety validator added during
the 0.2.0 security audit -- the check that refuses to start with a default/short JWT secret --
was carried as DOCUMENTED / NOT TESTED. That claim was wrong: `pydantic_settings` 2.14.0 imports
here. This file converts that security check from "reasoned correct" to actually executed.

Every test constructs `Settings(_env_file=None, ...)` explicitly so the developer's real `.env`
(if any) can never leak into a test result -- values under test come from the call, nothing else.

Dual-mode: runnable under pytest, or directly via `PYTHONPATH=. python3 tests/test_config.py`.
"""
from __future__ import annotations

from app.core.config import (
    _INSECURE_DEFAULT_JWT_SECRET,
    _MIN_PRODUCTION_JWT_SECRET_LENGTH,
    Settings,
)

_GOOD_SECRET = "x" * 64


def _settings(**overrides) -> Settings:
    return Settings(_env_file=None, **overrides)


# --- production safety validator: the cases that MUST fail closed ---


def test_production_with_default_jwt_secret_refuses_to_start():
    """The exact regression the 0.2.0 security audit fixed: production + placeholder secret used
    to start successfully and sign tokens with a public, well-known string."""
    try:
        _settings(ENVIRONMENT="production", JWT_SECRET_KEY=_INSECURE_DEFAULT_JWT_SECRET)
    except ValueError as exc:
        assert "insecure default placeholder" in str(exc)
        return
    raise AssertionError("production + default JWT secret was accepted; it must raise")


def test_production_with_short_jwt_secret_refuses_to_start():
    short = "a" * (_MIN_PRODUCTION_JWT_SECRET_LENGTH - 1)
    try:
        _settings(ENVIRONMENT="production", JWT_SECRET_KEY=short)
    except ValueError as exc:
        assert str(_MIN_PRODUCTION_JWT_SECRET_LENGTH) in str(exc)
        return
    raise AssertionError("production + short JWT secret was accepted; it must raise")


def test_production_with_debug_true_refuses_to_start():
    try:
        _settings(ENVIRONMENT="production", JWT_SECRET_KEY=_GOOD_SECRET, DEBUG=True)
    except ValueError as exc:
        assert "DEBUG" in str(exc)
        return
    raise AssertionError("production + DEBUG=true was accepted; it must raise")


def test_secret_of_exactly_minimum_length_is_accepted():
    """Boundary case: the check is `< MIN`, so exactly MIN must pass. A previously untested
    off-by-one here would have locked out a legitimately-sized secret."""
    exact = "b" * _MIN_PRODUCTION_JWT_SECRET_LENGTH
    s = _settings(ENVIRONMENT="production", JWT_SECRET_KEY=exact)
    assert s.JWT_SECRET_KEY == exact


def test_production_with_real_secret_starts():
    s = _settings(ENVIRONMENT="production", JWT_SECRET_KEY=_GOOD_SECRET, DEBUG=False)
    assert s.ENVIRONMENT == "production"
    assert s.DEBUG is False


# --- the cases that must NOT fail: dev/staging keep the friendly placeholder ---


def test_development_with_default_secret_is_allowed():
    s = _settings()
    assert s.ENVIRONMENT == "development"
    assert s.JWT_SECRET_KEY == _INSECURE_DEFAULT_JWT_SECRET


def test_staging_with_default_secret_is_allowed():
    """Documents current, deliberate behaviour, not an endorsement: staging is NOT covered by the
    fail-closed check. If a staging deployment is internet-reachable this is a real exposure --
    recorded in docs/AUDIT_SECURITY.md rather than silently changed here, because tightening it
    is a behaviour change outside this part's scope."""
    s = _settings(ENVIRONMENT="staging")
    assert s.JWT_SECRET_KEY == _INSECURE_DEFAULT_JWT_SECRET


def test_development_with_debug_true_is_allowed():
    s = _settings(DEBUG=True)
    assert s.DEBUG is True


# --- rejected values (pydantic Literal enforcement, previously never executed) ---


def test_unknown_environment_is_rejected():
    try:
        _settings(ENVIRONMENT="prod")  # a plausible typo for "production"
    except Exception:
        return
    raise AssertionError("ENVIRONMENT='prod' was accepted; Literal must reject it")


def test_unknown_primary_provider_is_rejected():
    try:
        _settings(PROVIDER_PRIMARY="ALPHAVANTAGE")
    except Exception:
        return
    raise AssertionError("PROVIDER_PRIMARY='ALPHAVANTAGE' was accepted; Literal must reject it")


def test_provider_secondary_none_is_the_default():
    """Part A6's dual-source ingestion path is gated on this being the default -- if this ever
    changed, every default deployment would start double-fetching from a second provider."""
    assert _settings().PROVIDER_SECONDARY == "NONE"


# --- derived values and invariants ---


def test_cors_origins_list_splits_and_strips():
    s = _settings(CORS_ALLOWED_ORIGINS=" http://a.example , http://b.example ,, ")
    assert s.cors_origins_list == ["http://a.example", "http://b.example"]


def test_cors_origins_list_single_value():
    assert _settings().cors_origins_list == ["http://localhost:3000"]


def test_scoring_pillar_weights_sum_to_one():
    """The five pillar weights are separate settings with no validator tying them together. If
    they ever stop summing to 1.0, every overall score silently shifts scale."""
    s = _settings()
    total = (
        s.SCORE_WEIGHT_QUALITY
        + s.SCORE_WEIGHT_FINANCIAL_HEALTH
        + s.SCORE_WEIGHT_GROWTH
        + s.SCORE_WEIGHT_COMPETITIVE_ADVANTAGE
        + s.SCORE_WEIGHT_VALUATION
    )
    assert abs(total - 1.0) < 1e-9, f"pillar weights sum to {total}, not 1.0"


def test_default_terminal_growth_does_not_exceed_default_risk_free_rate():
    """A terminal growth rate above the risk-free rate implies a company outgrowing the economy
    forever. The DCF engine caps this at runtime (cap_terminal_growth_at_risk_free); this asserts
    the shipped defaults don't rely on that cap to be sane in the first place."""
    s = _settings()
    assert s.DEFAULT_DCF_TERMINAL_GROWTH <= s.DEFAULT_RISK_FREE_RATE


def test_margin_of_safety_thresholds_are_ordered():
    s = _settings()
    assert s.DEFAULT_STRONG_BUY_MOS > s.DEFAULT_BUY_MOS > 0


def test_celery_soft_time_limit_is_below_hard_time_limit():
    """If soft >= hard, the soft-limit warning never fires and a stuck task is killed with no
    graceful-shutdown window."""
    s = _settings()
    assert s.CELERY_TASK_SOFT_TIME_LIMIT_SECONDS < s.CELERY_TASK_TIME_LIMIT_SECONDS


ALL_TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")]

if __name__ == "__main__":
    passed = failed = 0
    for t in ALL_TESTS:
        try:
            t()
            print(f"PASS  {t.__name__}")
            passed += 1
        except Exception as exc:  # noqa: BLE001
            print(f"FAIL  {t.__name__}: {exc}")
            failed += 1
    print(f"\n{passed}/{passed + failed} passed")
    raise SystemExit(1 if failed else 0)
