"""File upload endpoint + image serving endpoint — auto-converts to WebP"""
import io
import os
import uuid
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from fastapi.responses import Response

from app.api.deps import get_admin_user
from app.core.models.user import User

try:
    from PIL import Image as PILImage
    _PIL_OK = True
except ImportError:
    _PIL_OK = False

_HERE = os.path.dirname(os.path.abspath(__file__))
_ROOT = os.path.abspath(os.path.join(_HERE, "../../.."))
UPLOAD_DIR = os.path.join(_ROOT, "static", "uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)

ALLOWED_TYPES = {"image/jpeg", "image/png", "image/webp", "image/gif", "image/jpg"}
MIME_MAP = {
    ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
    ".png": "image/png", ".webp": "image/webp",
    ".gif": "image/gif",
}
MAX_SIZE = 5 * 1024 * 1024
WEBP_QUALITY = 85          # WebP 压缩质量 (1-100)
MAX_DIMENSION = 1600       # 长边最大像素，超出则等比缩小

router = APIRouter(tags=["upload"])


def _to_webp(raw: bytes, animated_ok: bool = False) -> bytes:
    """Convert raw image bytes to WebP. Returns WebP bytes."""
    img = PILImage.open(io.BytesIO(raw))

    # GIF 动图：保留原格式
    if getattr(img, "is_animated", False) and animated_ok:
        return raw

    # 转 RGB（去掉 alpha 时用白底合成，保留 RGBA 透明）
    if img.mode not in ("RGB", "RGBA", "L"):
        img = img.convert("RGBA" if "A" in img.mode else "RGB")

    # 等比缩小长边超过 MAX_DIMENSION 的图
    w, h = img.size
    if max(w, h) > MAX_DIMENSION:
        ratio = MAX_DIMENSION / max(w, h)
        img = img.resize((int(w * ratio), int(h * ratio)), PILImage.LANCZOS)

    out = io.BytesIO()
    img.save(out, format="WEBP", quality=WEBP_QUALITY, method=4)
    return out.getvalue()


@router.post("/upload", summary="Upload image (auto-converted to WebP)")
async def upload_image(
    file: UploadFile = File(...),
    admin_user: User = Depends(get_admin_user),
):
    if file.content_type not in ALLOWED_TYPES:
        raise HTTPException(status_code=400, detail="Only JPG/PNG/WebP/GIF allowed")

    content = await file.read()
    if len(content) > MAX_SIZE:
        raise HTTPException(status_code=400, detail="Image must be under 5MB")

    # ── WebP 转换 ──────────────────────────────────────────────
    if _PIL_OK:
        try:
            content = _to_webp(content)
            ext = ".webp"
        except Exception:
            # 转换失败则保留原格式
            ext = os.path.splitext(file.filename or "")[1].lower() or ".jpg"
    else:
        ext = os.path.splitext(file.filename or "")[1].lower() or ".jpg"

    filename = f"{uuid.uuid4().hex}{ext}"
    filepath = os.path.join(UPLOAD_DIR, filename)

    with open(filepath, "wb") as f:
        f.write(content)

    return {"url": f"/api/static/uploads/{filename}", "filename": filename}


@router.get("/static/uploads/{filename}", summary="Serve uploaded image", include_in_schema=False)
async def serve_upload(filename: str):
    filename = os.path.basename(filename)
    filepath = os.path.join(UPLOAD_DIR, filename)
    if not os.path.isfile(filepath):
        raise HTTPException(status_code=404, detail="File not found")
    ext = os.path.splitext(filename)[1].lower()
    mime = MIME_MAP.get(ext, "application/octet-stream")
    with open(filepath, "rb") as f:
        content = f.read()
    return Response(content=content, media_type=mime)
