"""
tests/test_deployment.py
========================
Smoke tests for a live deployment.  These tests hit a REAL running server —
they are NOT unit tests and require the full stack (FastAPI + built frontend).

Skipped by default.  Enable with --run-deployment:

    # Against localhost (default)
    pytest tests/test_deployment.py -v --run-deployment

    # Against a remote server
    pytest tests/test_deployment.py -v --run-deployment --base-url http://192.168.1.10:8000

    # With API key authentication enabled on the server
    pytest tests/test_deployment.py -v --run-deployment --api-key my-secret

Prerequisites:
    - Server is running: uvicorn api:app --host 0.0.0.0 --port 8000
    - Frontend is built: bash scripts/build_frontend.sh
"""

import pytest
import httpx


# ── Fixtures ──────────────────────────────────────────────────────────────────

@pytest.fixture(scope="module")
def base_url(request):
    return request.config.getoption("--base-url").rstrip("/")


@pytest.fixture(scope="module")
def headers(request):
    key = request.config.getoption("--api-key")
    return {"X-API-Key": key} if key else {}


@pytest.fixture(scope="module")
def client(base_url, headers):
    with httpx.Client(base_url=base_url, headers=headers, timeout=30.0) as c:
        yield c


# ── Health & monitoring ───────────────────────────────────────────────────────

@pytest.mark.deployment
class TestHealth:

    def test_health_returns_ok(self, client):
        resp = client.get("/health")
        assert resp.status_code == 200
        data = resp.json()
        assert data["statut"] == "ok"
        assert "modele" in data

    def test_metrics_has_required_keys(self, client):
        resp = client.get("/metrics")
        assert resp.status_code == 200
        data = resp.json()
        for key in ("total_requetes", "duree_moyenne_ms", "cout_total_usd"):
            assert key in data, f"Missing key: {key}"


# ── Frontend (Vite dist) ──────────────────────────────────────────────────────

@pytest.mark.deployment
class TestFrontend:

    def test_v2_returns_html(self, client):
        """FastAPI serves frontend/v2/dist/index.html at /v2."""
        resp = client.get("/v2", follow_redirects=True)
        assert resp.status_code == 200
        ct = resp.headers.get("content-type", "")
        assert "text/html" in ct, f"Expected HTML, got: {ct}"

    def test_v2_title_correct(self, client):
        """Built index.html must contain the page title."""
        resp = client.get("/v2", follow_redirects=True)
        assert resp.status_code == 200
        assert "Mercator" in resp.text, "Title 'Mercator' not found in /v2 HTML"

    def test_v2_references_assets(self, client):
        """Built index.html must reference the bundled JS in /assets/."""
        resp = client.get("/v2", follow_redirects=True)
        assert "/assets/" in resp.text, "No /assets/ reference found — frontend may not be built"

    def test_assets_js_served(self, client):
        """/assets/ route is mounted and serves at least one JS file."""
        page = client.get("/v2", follow_redirects=True)
        assert page.status_code == 200
        import re
        match = re.search(r'/assets/([\w\-\.]+\.js)', page.text)
        assert match, "Could not find a JS asset path in /v2 HTML"
        asset_url = f"/assets/{match.group(1)}"
        resp = client.get(asset_url)
        assert resp.status_code == 200
        ct = resp.headers.get("content-type", "")
        assert "javascript" in ct or "text/plain" in ct, f"Unexpected content-type for JS: {ct}"


# ── Data API endpoints ────────────────────────────────────────────────────────

@pytest.mark.deployment
class TestDataEndpoints:

    def test_map_data_returns_geojson(self, client):
        """/map-data must return a GeoJSON FeatureCollection."""
        resp = client.get("/map-data")
        assert resp.status_code == 200
        data = resp.json()
        assert data.get("type") == "FeatureCollection"
        assert isinstance(data.get("features"), list)
        assert len(data["features"]) > 0, "/map-data returned 0 features"

    def test_map_data_features_have_iris_properties(self, client):
        resp = client.get("/map-data")
        feature = resp.json()["features"][0]
        props = feature.get("properties", {})
        for key in ("code_iris", "nom_commune", "danger_score"):
            assert key in props, f"Missing property: {key}"

    def test_ui_features_returns_json(self, client):
        resp = client.get("/api/v2/ui-features")
        assert resp.status_code == 200
        assert resp.headers.get("content-type", "").startswith("application/json")

    def test_iris_pressure_known_iris(self, client):
        """/api/v2/iris-pressure/{code_iris} returns NPI/SPS/BPS for a known IRIS."""
        map_resp = client.get("/map-data")
        assert map_resp.status_code == 200
        features = map_resp.json()["features"]
        code = features[0]["properties"]["code_iris"]

        resp = client.get(f"/api/v2/iris-pressure/{code}")
        # 404 is acceptable if the IRIS has no pressure data (non-residential)
        assert resp.status_code in (200, 404)
        if resp.status_code == 200:
            data = resp.json()
            for key in ("npi", "sps", "bps"):
                assert key in data, f"Missing key in iris-pressure response: {key}"

    def test_iris_pressure_unknown_code_returns_404(self, client):
        resp = client.get("/api/v2/iris-pressure/000000000")
        assert resp.status_code == 404

    def test_iris_evolution_returns_series(self, client):
        map_resp = client.get("/map-data")
        code = map_resp.json()["features"][0]["properties"]["code_iris"]
        resp = client.get(f"/iris-evolution/{code}")
        assert resp.status_code == 200
        data = resp.json()
        assert "series" in data

    def test_flood_zones_returns_three_scenarios(self, client):
        resp = client.get("/flood-zones?lat=50.63&lng=3.06")
        assert resp.status_code == 200
        data = resp.json()
        for key in ("frequent", "moyen", "rare"):
            assert key in data

    def test_flood_zones_missing_param_returns_422(self, client):
        resp = client.get("/flood-zones?lat=50.63")
        assert resp.status_code == 422

    def test_flood_polygons_returns_geojson(self, client):
        resp = client.get(
            "/flood-polygons?min_lng=3.0&min_lat=50.5&max_lng=3.1&max_lat=50.7&scenario=moyen"
        )
        assert resp.status_code == 200
        data = resp.json()
        assert data.get("type") == "FeatureCollection"

    def test_nearby_sales_returns_json(self, client):
        resp = client.get(
            "/nearby-sales?lat=50.63&lng=3.06&type_local=Appartement&limit=5"
        )
        assert resp.status_code == 200
        data = resp.json()
        assert "count" in data

    def test_poi_returns_geojson(self, client):
        resp = client.get("/poi?types=gare")
        assert resp.status_code == 200
        data = resp.json()
        assert data.get("type") == "FeatureCollection"

    def test_seveso_sites_returns_geojson(self, client):
        resp = client.get("/seveso-sites")
        assert resp.status_code in (200, 503)
        if resp.status_code == 200:
            assert resp.json().get("type") == "FeatureCollection"


# ── Root redirect ─────────────────────────────────────────────────────────────

@pytest.mark.deployment
class TestRouting:

    def test_root_redirects_to_docs(self, client):
        resp = client.get("/", follow_redirects=False)
        assert resp.status_code in (301, 302, 307, 308)
        assert "/docs" in resp.headers.get("location", "")

    def test_docs_returns_html(self, client):
        resp = client.get("/docs", follow_redirects=True)
        assert resp.status_code == 200
        assert "text/html" in resp.headers.get("content-type", "")
