# retoor <retoor@molodetz.nl>

import io
import uuid
import requests
from PIL import Image
from tests.conftest import BASE_URL
from devplacepy.database import get_table
JSON_media = {"Accept": "application/json"}
def _png_bytes_media(color=(200, 30, 30)):
    buf = io.BytesIO()
    Image.new("RGB", (8, 8), color).save(buf, "PNG")
    return buf.getvalue()
def _signup_media(prefix="media"):
    s = requests.Session()
    name = f"{prefix}_{uuid.uuid4().hex[:10]}"
    s.post(
        f"{BASE_URL}/auth/signup",
        data={
            "username": name,
            "email": f"{name}@test.devplace",
            "password": "secret123",
            "confirm_password": "secret123",
            "birth_date": "1990-01-01",
            "accept_terms": "1",
        },
        allow_redirects=True,
    )
    return s, name
def _login_media(seeded_db, who):
    s = requests.Session()
    creds = seeded_db[who]
    s.post(
        f"{BASE_URL}/auth/login",
        data={"email": creds["email"], "password": creds["password"]},
        allow_redirects=True,
    )
    return s
def _upload_media(s, name="pic.png", content=None, mime="image/png"):
    files = {"file": (name, content if content is not None else _png_bytes_media(), mime)}
    r = s.post(f"{BASE_URL}/uploads/upload", files=files)
    assert r.status_code == 201, r.text
    return r.json()["uid"]
def _create_post_media(s, attachment_uids, title="media post"):
    r = s.post(
        f"{BASE_URL}/posts/create",
        data={
            "content": "A post that carries media for the gallery tests.",
            "title": title,
            "topic": "random",
            "attachment_uids": attachment_uids,
        },
        allow_redirects=True,
    )
    assert r.status_code == 200, r.text[:300]
    assert "/posts/" in r.url, r.url
    return r.url
def _create_project_media(s, attachment_uids, title="Media Project"):
    r = s.post(
        f"{BASE_URL}/projects/create",
        data={
            "title": title,
            "description": "Project with media for gallery tests.",
            "project_type": "software",
            "platforms": "linux",
            "status": "In Development",
            "attachment_uids": attachment_uids,
        },
        allow_redirects=True,
    )
    assert r.status_code == 200, r.text[:300]
    assert "/projects/" in r.url, r.url
    return r.url
def _media_json(session, username):
    r = session.get(f"{BASE_URL}/profile/{username}?tab=media", headers=JSON_media)
    assert r.status_code == 200, r.text[:300]
    return r.json()
def _media_uids(session, username):
    return [m["uid"] for m in _media_json(session, username)["media"]]
def _seed_media_via_browser(page, title="ui media"):
    up = page.request.post(
        f"{BASE_URL}/uploads/upload",
        multipart={
            "file": {
                "name": "pic.png",
                "mimeType": "image/png",
                "buffer": _png_bytes_media(),
            }
        },
    )
    assert up.ok, up.text()
    uid = up.json()["uid"]
    post = page.request.post(
        f"{BASE_URL}/posts/create",
        form={
            "content": "media for the ui gallery test",
            "title": title,
            "topic": "random",
            "attachment_uids": uid,
        },
    )
    assert post.ok, post.text()
    return uid
def _media_uids_via_page(page, username):
    resp = page.request.get(f"{BASE_URL}/profile/{username}?tab=media", headers=JSON_media)
    return [m["uid"] for m in resp.json()["media"]]


def test_delete_requires_login(app_server):
    owner, name = _signup_media()
    uid = _upload_media(owner)
    _create_post_media(owner, uid)
    anon = requests.Session()
    r = anon.post(f"{BASE_URL}/media/{uid}/delete", headers=JSON_media)
    assert r.status_code == 401


def test_delete_nonexistent_media(app_server):
    s, _ = _signup_media()
    r = s.post(f"{BASE_URL}/media/nonexistent-uid/delete", headers=JSON_media)
    assert r.status_code in (302, 303, 404)


def test_member_cannot_delete_other_members_media(app_server):
    owner, owner_name = _signup_media("owner")
    uid = _upload_media(owner)
    _create_post_media(owner, uid)
    attacker, _ = _signup_media("attacker")
    r = attacker.post(f"{BASE_URL}/media/{uid}/delete", headers=JSON_media)
    assert r.status_code == 403
    # still visible to the owner
    assert uid in _media_uids(owner, owner_name)


def test_owner_soft_deletes_own_media(app_server):
    owner, name = _signup_media()
    uid = _upload_media(owner)
    _create_post_media(owner, uid)
    assert uid in _media_uids(owner, name)

    r = owner.post(f"{BASE_URL}/media/{uid}/delete", headers=JSON_media)
    assert r.status_code == 200
    assert r.json()["ok"] is True

    # gone from the gallery (parent-object hiding is asserted in
    # test_soft_delete_hides_attachment_from_feed)
    assert uid not in _media_uids(owner, name)


def test_soft_delete_hides_attachment_from_feed(app_server):
    # The parent-object invariant: a soft-deleted attachment disappears from the place it
    # was attached. The feed reads attachments via the raw-query batch helper, so this is
    # a reliable end-to-end check that the relation is hidden (not unlinked).
    s, name = _signup_media()
    uid = _upload_media(s)
    _create_post_media(s, uid, title="feed invariant post")

    def attached_on_feed():
        posts = s.get(f"{BASE_URL}/feed", headers=JSON_media).json().get("posts", [])
        for item in posts:
            uids = [a.get("uid") for a in (item.get("attachments") or [])]
            if uid in uids:
                return True
        return False

    assert attached_on_feed()
    r = s.post(f"{BASE_URL}/media/{uid}/delete", headers=JSON_media)
    assert r.status_code == 200
    assert not attached_on_feed()


def test_admin_can_delete_any_media(seeded_db):
    owner, owner_name = _signup_media("victim")
    uid = _upload_media(owner)
    _create_post_media(owner, uid)
    admin = _login_media(seeded_db, "alice")
    r = admin.post(f"{BASE_URL}/media/{uid}/delete", headers=JSON_media)
    assert r.status_code == 200
    assert uid not in _media_uids(owner, owner_name)


def test_admin_trash_lists_deleted_media(seeded_db):
    owner, owner_name = _signup_media("trashed")
    uid = _upload_media(owner)
    _create_post_media(owner, uid)
    owner.post(f"{BASE_URL}/media/{uid}/delete", headers=JSON_media)

    admin = _login_media(seeded_db, "alice")
    data = admin.get(f"{BASE_URL}/admin/media", headers=JSON_media).json()
    item = next((m for m in data["media"] if m["uid"] == uid), None)
    assert item is not None
    assert item["uploader"] == owner_name
    assert item["deleted_at"]
