"""
Sicherheits-Regression für Release-Konfiguration (OpenAPI, Health-Ready, Legacy-Routen).

Läuft ohne PostgreSQL, wo möglich (TestClient + Subprocess mit frischem Import).
CI: scripts/security_release_checks.py
"""
from __future__ import annotations

import os
import subprocess
import sys
from pathlib import Path
from unittest.mock import patch

import pytest
from fastapi.testclient import TestClient

os.environ.setdefault("SKIP_DB_MIGRATE", "1")

from auth import require_auth
from main import app

BACKEND_ROOT = Path(__file__).resolve().parents[1]


@pytest.fixture
def client() -> TestClient:
    return TestClient(app)


@pytest.fixture(autouse=True)
def _clear_auth_override():
    yield
    app.dependency_overrides.pop(require_auth, None)


def test_legacy_get_profile_uses_session_only(client: TestClient) -> None:
    """SEC-01: /api/profile darf nur das Session-Profil liefern."""

    def auth_user() -> dict:
        return {"profile_id": 901, "role": "trainer"}

    app.dependency_overrides[require_auth] = auth_user
    with patch("routers.profiles.profile_document") as pd_mock:
        pd_mock.return_value = {"id": 901, "name": "T"}
        r = client.get("/api/profile", headers={"X-Auth-Token": "dummy"})
        assert r.status_code == 200
        pd_mock.assert_called_once_with("901")


def _run_fresh_import_int(code: str, env: dict) -> subprocess.CompletedProcess:
    merged = {**os.environ, **env, "SKIP_DB_MIGRATE": "1"}
    return subprocess.run(
        [sys.executable, "-c", code],
        cwd=str(BACKEND_ROOT),
        env=merged,
        capture_output=True,
        text=True,
        check=False,
    )


@pytest.mark.parametrize(
    "extra_env, expect_openapi",
    [
        ({"ENVIRONMENT": "development"}, True),
        ({"ENVIRONMENT": "production"}, False),
        ({"ENVIRONMENT": "production", "PUBLIC_OPENAPI": "true"}, True),
    ],
)
def test_openapi_urls_match_environment(extra_env: dict, expect_openapi: bool) -> None:
    snippet = f"""
from main import app
assert (app.openapi_url is not None) == {expect_openapi}
assert (app.docs_url is not None) == {expect_openapi}
"""
    proc = _run_fresh_import_int(snippet, extra_env)
    assert proc.returncode == 0, proc.stderr + proc.stdout


def test_health_ready_minimal_body_in_production() -> None:
    snippet = """
from fastapi.testclient import TestClient
from main import app
c = TestClient(app)
r = c.get("/api/health/ready")
r.raise_for_status()
j = r.json()
assert "tables" not in j
assert "detail" not in j
assert "schema_migrations_count" not in j
assert "status" in j and "database" in j and "schema_complete" in j
"""
    proc = _run_fresh_import_int(
        snippet,
        {"ENVIRONMENT": "production"},
    )
    assert proc.returncode == 0, proc.stderr + proc.stdout


def test_health_ready_full_detail_when_flag_in_production() -> None:
    snippet = """
from fastapi.testclient import TestClient
from main import app
c = TestClient(app)
r = c.get("/api/health/ready")
r.raise_for_status()
j = r.json()
assert "tables" in j
assert "schema_migrations_count" in j
"""
    proc = _run_fresh_import_int(
        snippet,
        {"ENVIRONMENT": "production", "HEALTH_READY_PUBLIC_DETAIL": "1"},
    )
    assert proc.returncode == 0, proc.stderr + proc.stdout


def test_api_attachments_x_content_type_options_nosniff(client: TestClient) -> None:
    """Globales Middleware: keine MIME-Sniffing-Heuristik für API/Health."""
    r = client.get("/health")
    assert r.status_code == 200
    assert r.headers.get("x-content-type-options") == "nosniff"
    r2 = client.get("/api/version")
    assert r2.status_code == 200
    assert r2.headers.get("x-content-type-options") == "nosniff"


def test_public_media_static_not_mounted_by_default() -> None:
    """/media/-StaticFiles-Mount darf ohne ALLOW_PUBLIC_MEDIA_STATIC nicht aktiv sein."""
    snippet = """
from main import app
mounted = [getattr(r, 'path', '') for r in app.routes]
assert not any(p == '/media' for p in mounted), (
    "ALLOW_PUBLIC_MEDIA_STATIC aktiv – /media oeffentlich erreichbar. Vor Deploy entfernen."
)
"""
    proc = _run_fresh_import_int(snippet, {"ENVIRONMENT": "production"})
    assert proc.returncode == 0, proc.stderr + proc.stdout


def test_allow_public_media_static_activates_media_mount() -> None:
    """Dokumentiert: ALLOW_PUBLIC_MEDIA_STATIC=1 aktiviert /media ohne Authentifizierung."""
    snippet = """
from main import app
mounted = [getattr(r, 'path', '') for r in app.routes]
assert any(p == '/media' for p in mounted), "/media-Mount wurde nicht aktiviert"
"""
    proc = _run_fresh_import_int(snippet, {"ALLOW_PUBLIC_MEDIA_STATIC": "1"})
    assert proc.returncode == 0, proc.stderr + proc.stdout
