"""Marketplace helper utilities: slug/SKU generation and image storage.

Image files are stored under ``LISTING_IMAGE_FOLDER`` with opaque, unique
filenames. Only the filename is persisted (``ListingImage.image_path``); the
public URL is always built via ``url_for('marketplace.listing_image', ...)``.
"""

from __future__ import annotations

import io
import re
import uuid

from flask import current_app
from PIL import Image
from werkzeug.datastructures import FileStorage
from werkzeug.utils import secure_filename

_SLUG_STRIP = re.compile(r"[^a-z0-9]+")


def slugify(text: str) -> str:
    """Lowercase, hyphenate and trim a string into a URL-safe slug fragment."""
    return _SLUG_STRIP.sub("-", text.lower()).strip("-")


def generate_slug(title: str) -> str:
    """Build a unique, SEO-friendly slug from a title.

    A short random suffix guarantees uniqueness without a database round-trip,
    and the result is capped at the column length (255).
    """
    base = slugify(title)[:240] or "listing"
    return f"{base}-{uuid.uuid4().hex[:8]}"


def generate_sku() -> str:
    """Return a human-readable, unique listing reference (e.g. ``SB-1A2B3C4D``)."""
    return f"SB-{uuid.uuid4().hex[:8].upper()}"


def allowed_image(filename: str) -> bool:
    """Return True if the filename has an allowed image extension."""
    if "." not in filename:
        return False
    ext = filename.rsplit(".", 1)[1].lower()
    return ext in current_app.config["ALLOWED_IMAGE_EXTENSIONS"]


def save_listing_image(file: FileStorage) -> str:
    """Validate and persist one uploaded image; return the stored filename.

    The bytes are read once, verified as a real image with Pillow, then written
    to disk under a unique name. Raises ``ValueError`` if the file is not a valid
    image (callers validate beforehand, but this is the last line of defence).
    """
    ext = file.filename.rsplit(".", 1)[1].lower()
    data = file.read()
    try:
        Image.open(io.BytesIO(data)).verify()
    except Exception as exc:  # noqa: BLE001 - any Pillow failure means "not an image"
        raise ValueError("Uploaded file is not a valid image.") from exc

    # secure_filename only to derive a safe extension; the stored name is opaque.
    safe_ext = secure_filename(f"x.{ext}").rsplit(".", 1)[1]
    stored_name = f"{uuid.uuid4().hex}.{safe_ext}"
    destination = current_app.config["LISTING_IMAGE_FOLDER"] / stored_name
    with open(destination, "wb") as out:
        out.write(data)
    return stored_name
