"""ذخیره‌سازی عکس مشتری — روی دیسک محلی (پیش‌فرض) یا S3/R2 (پیکربندی‌پذیر برای دیپلوی).

فقط «کلید» فایل ذخیره‌شده در Customer.photo_path نگه داشته می‌شود، نه مسیر مطلق —
تا تغییر بک‌اند ذخیره‌سازی بدون تغییر دیتابیس ممکن باشد.
"""
import uuid
from pathlib import Path

from flask import current_app, send_from_directory

ALLOWED_EXT = {"png", "jpg", "jpeg", "webp"}
MAX_DIMENSION = 640


class InvalidPhotoError(ValueError):
    """فایل آپلودشده تصویر قابل‌خواندن نیست."""


def allowed_file(filename: str) -> bool:
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXT


def _prepare_image(file_storage):
    from PIL import Image, ImageOps  # سنگینه و فقط موقع آپلود عکس لازمه

    try:
        img = Image.open(file_storage.stream)
        # عکس گوشی جهتش رو فقط در EXIF نگه می‌داره؛ بدون این، عکس عمودی خوابیده ذخیره می‌شد
        img = ImageOps.exif_transpose(img)
        img.thumbnail((MAX_DIMENSION, MAX_DIMENSION))
        return img if img.mode == "RGB" else img.convert("RGB")
    except Exception as exc:  # فایل خراب، غیرتصویری یا فرمت پشتیبانی‌نشده
        raise InvalidPhotoError("فایل انتخاب‌شده یک تصویر معتبر نیست") from exc


def save_photo(file_storage, customer_id: int) -> str:
    """عکس را ذخیره و کلید ذخیره‌شده را برمی‌گرداند (همیشه JPEG)."""
    img = _prepare_image(file_storage)
    key = f"{customer_id}-{uuid.uuid4().hex[:8]}.jpg"

    backend = current_app.config["PHOTO_STORAGE_BACKEND"]
    if backend == "local":
        photo_dir = current_app.config["LOCAL_PHOTO_DIR"]
        photo_dir.mkdir(parents=True, exist_ok=True)
        img.save(photo_dir / key, "JPEG", quality=88)
        return key

    raise NotImplementedError(f"Photo storage backend '{backend}' not implemented yet")


def delete_photo(key: str):
    """حذف عکس قبلی بعد از جایگزینی (تا فایل‌های بلااستفاده روی هاست جمع نشن)."""
    if not key:
        return
    backend = current_app.config["PHOTO_STORAGE_BACKEND"]
    if backend == "local":
        path = Path(current_app.config["LOCAL_PHOTO_DIR"]) / key
        try:
            if path.is_file():
                path.unlink()
        except OSError:
            current_app.logger.warning("حذف عکس قبلی ممکن نشد: %s", path)


def serve_photo(key: str):
    backend = current_app.config["PHOTO_STORAGE_BACKEND"]
    if backend == "local":
        # کلید فایل شامل uuid است و با هر بار تعویض عکس عوض می‌شود، پس کش طولانی خطر
        # نمایش عکس قدیمی ندارد و در عوض هر بار باز کردن پرونده یک رفت‌وبرگشت کمتر می‌شود.
        return send_from_directory(current_app.config["LOCAL_PHOTO_DIR"], key, max_age=2592000)
    raise NotImplementedError(f"Photo storage backend '{backend}' not implemented yet")


def photo_exists(key: str) -> bool:
    if not key:
        return False
    backend = current_app.config["PHOTO_STORAGE_BACKEND"]
    if backend == "local":
        return (Path(current_app.config["LOCAL_PHOTO_DIR"]) / key).exists()
    return False
