from urllib.parse import urlparse

from conftest import DEMO_CODE, NOCONSENT_CODE


async def test_photos_known_code_returns_200(client, demo_code):
    r = await client.get(f"/api/portal/photos?code={demo_code}")
    assert r.status_code == 200
    body = r.json()
    assert body["family_code"] == demo_code
    assert body["consent_given"] is True
    assert len(body["photos"]) == 2
    assert body["school_name"] == "École Test"
    assert body["pricing"]["print_10x15"] == 9


async def test_photos_hidden_until_consent(client):
    from core.db import get_db
    with get_db() as conn:
        conn.execute("UPDATE families SET consent_at=NULL WHERE code=?", (NOCONSENT_CODE,))
        conn.commit()
    r = await client.get(f"/api/portal/photos?code={NOCONSENT_CODE}")
    body = r.json()
    assert body["consent_given"] is False
    assert body["photos"] == []


async def test_photos_unknown_code_returns_404(client):
    assert (await client.get("/api/portal/photos?code=ZZZ-0000")).status_code == 404


async def test_photos_never_fall_back_to_placeholder_images(client):
    """Une famille sans photos reçoit une liste vide, jamais d'images aléatoires."""
    from core.db import get_db
    from core.timeutil import utcnow_iso
    with get_db() as conn:
        conn.execute("INSERT OR REPLACE INTO families (code, family_name, created_at, school_id, consent_at) "
                     "VALUES ('EMP-4004','Vide',?, 'ecole-test', ?)", (utcnow_iso(), utcnow_iso()))
        conn.commit()
    body = (await client.get("/api/portal/photos?code=EMP-4004")).json()
    assert body["photos"] == []
    assert body["photos_pending"] is True


async def test_photo_urls_are_signed_previews_not_originals(client, demo_code):
    photos = (await client.get(f"/api/portal/photos?code={demo_code}")).json()["photos"]
    for p in photos:
        assert p["url"].startswith("/api/media/preview/")
        assert "sig=" in p["url"] and "exp=" in p["url"]
        assert "/photos/" not in p["url"]


async def test_failed_lookups_are_rate_limited_per_ip(client):
    """Empêche de scanner l'espace des codes famille (seuls les ÉCHECS comptent)."""
    statuses = [(await client.get("/api/portal/photos?code=NOPE-0000")).status_code for _ in range(25)]
    assert 429 in statuses
    assert statuses[0] == 404


async def test_successful_lookups_do_not_burn_the_rate_limit(client, demo_code):
    statuses = [(await client.get(f"/api/portal/photos?code={demo_code}")).status_code for _ in range(30)]
    assert set(statuses) == {200}


async def test_path_traversal_code_is_rejected(client):
    assert (await client.get("/api/portal/photos?code=../../etc")).status_code == 404
