"""Icon upload API — POST /printers/{printer_id}/icon."""
from __future__ import annotations

import hashlib
import io
from pathlib import Path

from fastapi import APIRouter, UploadFile
from fastapi.responses import HTMLResponse
from PIL import Image

import imptune.config as cfg
from imptune.db.models import Icon, Printer

router = APIRouter(prefix="/printers")

MAX_ICON_BYTES = 750 * 1024  # 750 KB


@router.post("/{printer_id}/icon", response_class=HTMLResponse)
def upload_icon(printer_id: int, file: UploadFile) -> HTMLResponse:
    """Accept a printer icon PNG, validate it, store it, and update the Icon record.

    Validation rules:
    - Format: PNG only
    - Dimensions: exactly 256x256 pixels
    - Size: at most 750 KB

    Replaces any previously uploaded icon for this printer.
    Returns an HTMX-friendly HTML fragment.
    """
    # Check printer exists
    printer = Printer.get_or_none(Printer.id == printer_id)
    if printer is None:
        return HTMLResponse(
            content="<p>Printer not found.</p>",
            status_code=404,
        )

    # Read file (read one byte extra to detect oversized files)
    data = file.file.read(MAX_ICON_BYTES + 1)
    if len(data) > MAX_ICON_BYTES:
        return HTMLResponse(
            content="<p>Icon exceeds 750 KB limit.</p>",
            status_code=422,
        )

    # Validate with Pillow
    try:
        img = Image.open(io.BytesIO(data))
    except Exception:
        return HTMLResponse(
            content="<p>Icon must be PNG format.</p>",
            status_code=422,
        )

    if img.format != "PNG":
        return HTMLResponse(
            content="<p>Icon must be PNG format.</p>",
            status_code=422,
        )

    if img.size != (256, 256):
        return HTMLResponse(
            content=f"<p>Icon must be 256x256 pixels, got {img.size}.</p>",
            status_code=422,
        )

    # Store SHA256-addressed on disk
    sha256 = hashlib.sha256(data).hexdigest()
    icons_dir = Path(cfg.DATA_DIR) / "icons"
    icons_dir.mkdir(parents=True, exist_ok=True)
    icon_path = icons_dir / sha256
    icon_path.write_bytes(data)

    # Replace existing Icon record for this printer
    Icon.delete().where(Icon.printer == printer_id).execute()
    Icon.create(
        printer=printer_id,
        sha256=sha256,
        original_filename=file.filename or "icon.png",
        size_bytes=len(data),
    )

    return HTMLResponse(
        content="<p>Icon uploaded successfully</p>",
        status_code=200,
    )
