"""Tests for garment analysis and management endpoints."""

import uuid

import pytest
from httpx import AsyncClient


@pytest.mark.asyncio
async def test_analyze_garment_global_user(client: AsyncClient, sample_jpeg: bytes):
    """POST /garments/analyze with no user_id → global user, face_status=skipped."""
    resp = await client.post(
        "/api/v1/garments/analyze",
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["face_status"] == "not_used"
    assert data["user_id"] == "00000000-0000-0000-0000-000000000000"
    assert len(data["garments"]) >= 1

    garment = data["garments"][0]
    assert garment["category_main"] == "top"
    assert garment["category_sub"] == "t-shirt"
    assert garment["tags"]["color"] == ["black"]
    assert garment["id"] is not None
    # Ghost should be null (separate step now)
    assert garment["ghost_image_url"] is None


@pytest.mark.asyncio
async def test_analyze_garment_with_user_id(client: AsyncClient, sample_jpeg: bytes):
    """POST /garments/analyze with explicit user_id → face_status=skipped."""
    user_id = "00000000-0000-0000-0000-000000000000"
    resp = await client.post(
        "/api/v1/garments/analyze",
        data={"user_id": user_id},
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["face_status"] == "not_used"
    assert data["user_id"] == user_id
    assert len(data["garments"]) >= 1


@pytest.mark.asyncio
async def test_analyze_with_face_id(client: AsyncClient, sample_jpeg: bytes):
    """POST /garments/analyze with use_face_id=true → face identification attempt."""
    resp = await client.post(
        "/api/v1/garments/analyze",
        data={"use_face_id": "true"},
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert "user_id" in data
    assert "garments" in data
    assert data["face_status"] in ("known", "unknown", "not_detected")


@pytest.mark.asyncio
async def test_analyze_without_face_id(client: AsyncClient, sample_jpeg: bytes):
    """POST /garments/analyze with use_face_id=false → global fallback."""
    resp = await client.post(
        "/api/v1/garments/analyze",
        data={"use_face_id": "false"},
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["face_status"] == "not_used"
    assert data["user_id"] == "00000000-0000-0000-0000-000000000000"


@pytest.mark.asyncio
async def test_get_garment_not_found(client: AsyncClient):
    """GET /garments/{id} with non-existent id → 404."""
    fake_id = uuid.uuid4()
    resp = await client.get(f"/api/v1/garments/{fake_id}")
    assert resp.status_code == 404


@pytest.mark.asyncio
async def test_delete_garment_not_found(client: AsyncClient):
    """DELETE /garments/{id} with non-existent id → 404."""
    fake_id = uuid.uuid4()
    resp = await client.delete(f"/api/v1/garments/{fake_id}")
    assert resp.status_code == 404


@pytest.mark.asyncio
async def test_garment_crud_lifecycle(client: AsyncClient, sample_jpeg: bytes):
    """Full lifecycle: analyze → get → delete."""
    # 1. Create via analyze
    resp = await client.post(
        "/api/v1/garments/analyze",
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    garment_id = resp.json()["garments"][0]["id"]

    # 2. Get detail
    resp = await client.get(f"/api/v1/garments/{garment_id}")
    assert resp.status_code == 200
    detail = resp.json()
    assert detail["id"] == garment_id
    assert detail["category_main"] == "top"

    # 3. Delete
    resp = await client.delete(f"/api/v1/garments/{garment_id}")
    assert resp.status_code == 200
    assert resp.json()["deleted"] is True

    # 4. Confirm deleted
    resp = await client.get(f"/api/v1/garments/{garment_id}")
    assert resp.status_code == 404


@pytest.mark.asyncio
async def test_ghost_generate_not_found(client: AsyncClient):
    """POST /garments/{id}/ghost with non-existent id → 404."""
    fake_id = uuid.uuid4()
    resp = await client.post(f"/api/v1/garments/{fake_id}/ghost")
    assert resp.status_code == 404


# ---------------------------------------------------------------------------
# auto_save=false flow: analyze_only → save → verify
# ---------------------------------------------------------------------------


@pytest.mark.asyncio
async def test_analyze_only_no_save(client: AsyncClient, sample_jpeg: bytes):
    """POST /garments/analyze with auto_save=false → analysis only, no DB records."""
    resp = await client.post(
        "/api/v1/garments/analyze",
        data={"auto_save": "false"},
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["saved"] is False
    assert data["source_image_path"] is not None
    assert len(data["garments"]) >= 1

    garment = data["garments"][0]
    assert garment["id"] is None  # Not saved to DB
    assert garment["category_main"] == "top"
    assert garment["source_image_url"] is not None


@pytest.mark.asyncio
async def test_analyze_only_then_save(client: AsyncClient, sample_jpeg: bytes):
    """Full flow: analyze(auto_save=false) → POST /save → garments persisted."""
    # 1. Analyze only
    resp = await client.post(
        "/api/v1/garments/analyze",
        data={"auto_save": "false"},
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    analyze_data = resp.json()
    assert analyze_data["saved"] is False
    source_path = analyze_data["source_image_path"]

    # 2. Save selected garments
    save_body = {
        "source_image_path": source_path,
        "garments": [
            {
                "category_main": g["category_main"],
                "category_sub": g.get("category_sub"),
                "description": g.get("description"),
                "tags": g.get("tags"),
            }
            for g in analyze_data["garments"]
        ],
    }
    resp = await client.post("/api/v1/garments/save", json=save_body)
    assert resp.status_code == 200
    save_data = resp.json()
    assert len(save_data["garments"]) == len(analyze_data["garments"])

    # Saved garments have IDs
    for g in save_data["garments"]:
        assert g["id"] is not None

    # 3. Verify garment exists in DB
    garment_id = save_data["garments"][0]["id"]
    resp = await client.get(f"/api/v1/garments/{garment_id}")
    assert resp.status_code == 200
    assert resp.json()["category_main"] == "top"


@pytest.mark.asyncio
async def test_analyze_auto_save_default_true(client: AsyncClient, sample_jpeg: bytes):
    """POST /garments/analyze without auto_save → defaults to saved=True."""
    resp = await client.post(
        "/api/v1/garments/analyze",
        files={"image": ("test.jpg", sample_jpeg, "image/jpeg")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["saved"] is True
    assert data["garments"][0]["id"] is not None
