"""Tests for the clawID REST API (uses httpx async test client)."""

import io
import json

import numpy as np
import pytest
from fastapi.testclient import TestClient
from PIL import Image

from clawid.api import create_app
from clawid.storage import SQLiteStore


def make_png_bytes(size=(512, 512)) -> bytes:
    arr = np.random.default_rng(99).integers(0, 256, (*size, 3), dtype=np.uint8)
    buf = io.BytesIO()
    Image.fromarray(arr).save(buf, format="PNG")
    return buf.getvalue()


@pytest.fixture
def client():
    store = SQLiteStore(":memory:")
    app = create_app(store=store)
    return TestClient(app)


@pytest.fixture
def client_no_store():
    app = create_app(store=None)
    return TestClient(app)


# ── health ────────────────────────────────────────────────────────────────────

def test_health(client):
    r = client.get("/health")
    assert r.status_code == 200
    assert r.json()["status"] == "ok"
    assert r.json()["store"] == "SQLiteStore"


def test_health_no_store(client_no_store):
    r = client_no_store.get("/health")
    assert r.status_code == 200
    assert r.json()["store"] is None


# ── embed ─────────────────────────────────────────────────────────────────────

def test_embed_returns_png(client):
    r = client.post(
        "/v1/embed",
        data={"uid": "user1", "platform": "hawky.ai"},
        files={"image": ("test.png", make_png_bytes(), "image/png")},
    )
    assert r.status_code == 200
    assert r.headers["content-type"] == "image/png"
    assert "X-ClawID" in r.headers


def test_embed_clawid_in_header(client):
    r = client.post(
        "/v1/embed",
        data={"uid": "user2"},
        files={"image": ("test.png", make_png_bytes(), "image/png")},
    )
    clawid = r.headers.get("X-ClawID")
    assert clawid and len(clawid) == 36  # UUID format


def test_embed_persists_to_store(client):
    r = client.post(
        "/v1/embed",
        data={"uid": "store_user", "platform": "test"},
        files={"image": ("test.png", make_png_bytes(), "image/png")},
    )
    clawid = r.headers["X-ClawID"]
    # look it up
    r2 = client.get(f"/v1/asset/{clawid}")
    assert r2.status_code == 200
    assert r2.json()["metadata"]["uid"] == "store_user"


def test_embed_no_metadata_returns_422(client):
    r = client.post(
        "/v1/embed",
        files={"image": ("test.png", make_png_bytes(), "image/png")},
    )
    assert r.status_code == 422


def test_embed_invalid_image_returns_422(client):
    r = client.post(
        "/v1/embed",
        data={"uid": "x"},
        files={"image": ("bad.png", b"not an image", "image/png")},
    )
    assert r.status_code == 422


# ── detect ────────────────────────────────────────────────────────────────────

def test_detect_watermarked_image(client):
    # First embed
    r_embed = client.post(
        "/v1/embed",
        data={"uid": "detect_user", "platform": "test"},
        files={"image": ("test.png", make_png_bytes(), "image/png")},
    )
    wm_png = r_embed.content

    # Then detect
    r_detect = client.post(
        "/v1/detect",
        files={"image": ("wm.png", wm_png, "image/png")},
    )
    assert r_detect.status_code == 200
    body = r_detect.json()
    assert body["detected"] is True
    assert body["metadata"]["uid"] == "detect_user"


def test_detect_clean_image(client):
    r = client.post(
        "/v1/detect",
        files={"image": ("clean.png", make_png_bytes(), "image/png")},
    )
    assert r.status_code == 200
    assert r.json()["detected"] is False


# ── asset CRUD ────────────────────────────────────────────────────────────────

def test_get_asset_not_found(client):
    r = client.get("/v1/asset/no-such-id")
    assert r.status_code == 404


def test_delete_asset(client):
    r = client.post(
        "/v1/embed",
        data={"uid": "del_user"},
        files={"image": ("test.png", make_png_bytes(), "image/png")},
    )
    clawid = r.headers["X-ClawID"]
    r_del = client.delete(f"/v1/asset/{clawid}")
    assert r_del.status_code == 200
    assert r_del.json()["deleted"] is True
    assert client.get(f"/v1/asset/{clawid}").status_code == 404


def test_asset_endpoints_without_store(client_no_store):
    r = client_no_store.get("/v1/asset/anything")
    assert r.status_code == 503
