"""User profile image upload helpers."""

from __future__ import annotations

import uuid
from pathlib import Path

from fastapi import HTTPException, UploadFile, status
from sqlalchemy import inspect, text
from sqlalchemy.engine import Engine
from sqlalchemy.orm import Session

from app.config import get_settings
from app.models import User
from app.services.admin_service import uploads_base_dir

ALLOWED_USER_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"}
ALLOWED_USER_IMAGE_CONTENT_TYPES = {
    "image/jpeg",
    "image/jpg",
    "image/pjpeg",
    "image/png",
    "image/x-png",
    "image/gif",
    "image/webp",
}


def sync_users_profile_image_column(engine: Engine) -> None:
    """Ensure `users.profile_image` exists for legacy DBs."""
    try:
        insp = inspect(engine)
        if "users" not in insp.get_table_names():
            return
        cols = {c["name"] for c in insp.get_columns("users")}
    except Exception:
        return

    if "profile_image" in cols:
        return

    is_pg = engine.dialect.name == "postgresql"
    with engine.begin() as conn:
        if is_pg:
            conn.execute(text("ALTER TABLE users ADD COLUMN IF NOT EXISTS profile_image VARCHAR(512)"))
        else:
            try:
                conn.execute(text("ALTER TABLE users ADD COLUMN profile_image VARCHAR(512)"))
            except Exception:
                pass


def user_image_upload_dir() -> Path:
    dest = uploads_base_dir() / "user-profile"
    dest.mkdir(parents=True, exist_ok=True)
    return dest


def delete_user_profile_image(relative_path: str | None) -> None:
    if not relative_path:
        return
    path = user_image_upload_dir() / Path(relative_path).name
    if path.is_file():
        path.unlink()


async def save_user_profile_image(media: UploadFile) -> str:
    settings = get_settings()
    content_type = (media.content_type or "").split(";")[0].strip().lower()
    filename = media.filename or ""
    ext = Path(filename).suffix.lower()
    if not ext and content_type.startswith("image/"):
        ext = "." + content_type.split("/", 1)[1]

    if ext not in ALLOWED_USER_IMAGE_EXTENSIONS:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Unsupported image type. Allowed: {', '.join(sorted(ALLOWED_USER_IMAGE_EXTENSIONS))}",
        )
    if (
        content_type
        and content_type not in ALLOWED_USER_IMAGE_CONTENT_TYPES
        and not content_type.startswith("image/")
    ):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Unsupported image content type")

    data = await media.read()
    max_bytes = settings.community_max_upload_mb * 1024 * 1024
    if len(data) > max_bytes:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Image too large (max {settings.community_max_upload_mb} MB)",
        )
    if not data:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Empty image file")

    stored_name = f"{uuid.uuid4().hex}{ext}"
    dest = user_image_upload_dir() / stored_name
    dest.write_bytes(data)
    return f"user-profile/{stored_name}"


def set_user_profile_image(db: Session, user: User, image_path: str) -> User:
    delete_user_profile_image(getattr(user, "profile_image", None))
    user.profile_image = image_path
    db.commit()
    db.refresh(user)
    return user

