import os
import re
import time
import hashlib
import unicodedata
import logging
from typing import Optional
from pathlib import Path
from PIL import Image, UnidentifiedImageError
from fastapi import UploadFile
from unidecode import unidecode
import aiofiles

logger = logging.getLogger(__name__)

# Папки
BASE_DIR = Path(__file__).resolve().parent
ORIGINAL_DIR = BASE_DIR / "upload" / "original"
CONVERTED_DIR = BASE_DIR / "upload" / "converted"
PLACEHOLDER_PATH = BASE_DIR / "assets" / "placeholder.webp"

# Дозволені розширення
ALLOWED_EXTENSIONS = {".png", ".jpg", ".jpeg", ".heic", ".heif", ".svg", ".webp"}

# Фіктивний домен (зміниться згодом)
MEDIA_URL = "https://cms.xpro.com.ua/api/upload/"
ASSETS_URL = "https://cms.xpro.com.ua/api/assets/"

# Створення директорій
ORIGINAL_DIR.mkdir(parents=True, exist_ok=True)
CONVERTED_DIR.mkdir(parents=True, exist_ok=True)

# Генерація безпечного імені
def generate_safe_filename(original_name: str, prefix: str = "") -> str:
    base, ext = os.path.splitext(original_name)
    base = unidecode(base)
    base = unicodedata.normalize('NFKD', base)
    base = re.sub(r"[^\w\s-]", "", base)
    base = re.sub(r"\s+", "_", base).strip("_")
    hash_prefix = hashlib.md5(f"{base}_{time.time()}".encode()).hexdigest()[:8]
    if prefix:
        base = f"{prefix}_{base}"
    return f"{hash_prefix}_{base}{ext.lower()}"

# Збереження на диск
async def save_file_to_disk(upload_file: UploadFile, dest_folder: Path, subdir: str, filename: Optional[str] = None) -> str:
    full_dest = dest_folder / subdir
    full_dest.mkdir(parents=True, exist_ok=True)

    if filename is None:
        filename = generate_safe_filename(upload_file.filename)

    file_path = full_dest / filename

    async with aiofiles.open(file_path, "wb") as out_file:
        content = await upload_file.read()
        await out_file.write(content)

    # Повертаємо шлях для URL: upload/original/abc123_filename.jpg
    return f"{subdir}/{filename}"

# Основна логіка
async def handle_image_upload(file: UploadFile) -> str:
    """
    Приймає UploadFile, повертає повний URL до збереженого файлу або placeholder
    """
    logger.info(f"🖼️ Starting image upload process for file: {file.filename if file else 'None'}")

    if not file:
        logger.warning("❌ No file provided, returning placeholder")
        return f"{ASSETS_URL}placeholder.webp"

    filename = file.filename
    ext = Path(filename).suffix.lower()
    logger.info(f"📄 Processing file: {filename}, extension: {ext}")

    safe_filename = generate_safe_filename(filename)
    logger.info(f"🔄 Generated safe filename: {safe_filename}")

    # Зберігаємо оригінал завжди
    original_path = ORIGINAL_DIR / safe_filename
    logger.info(f"💾 Saving original to: {original_path}")

    contents = await file.read()
    with open(original_path, "wb") as f:
        f.write(contents)

    logger.info(f"✅ Original file saved: {original_path.exists()}, size: {len(contents)} bytes")

    # Якщо розширення невідоме або немає — просто повертаємо оригінал
    if not ext or ext not in ALLOWED_EXTENSIONS:
        logger.info(f"📦 Unknown or unrecognized extension, saving as-is")
        relative_path = f"original/{safe_filename}"
        final_url = f"{MEDIA_URL}{relative_path}"
        logger.info(f"✅ File saved successfully: {final_url}")
        return final_url

    # SVG — просто кладемо як є
    if ext == ".svg":
        logger.info("🎨 Processing SVG file")
        relative_path = f"original/{safe_filename}"
        final_url = f"{MEDIA_URL}{relative_path}"
        logger.info(f"✅ SVG saved successfully: {final_url}")
        return final_url

    # Інші — пробуємо перетворити в webp
    try:
        logger.info("🔄 Starting image conversion to WebP")
        image = Image.open(original_path)
        converted_name = Path(safe_filename).stem + ".webp"
        converted_path = CONVERTED_DIR / converted_name

        logger.info(f"💾 Converting to: {converted_path}")
        image.save(converted_path, "webp")

        # Перевіряємо чи файл створився
        if converted_path.exists():
            file_size = converted_path.stat().st_size
            logger.info(f"✅ WebP conversion successful: {converted_path}, size: {file_size} bytes")
        else:
            logger.error(f"❌ WebP file was not created: {converted_path}")

        final_url = f"{MEDIA_URL}converted/{converted_name}"
        logger.info(f"🌐 Final URL: {final_url}")
        return final_url

    except (UnidentifiedImageError, Exception) as e:
        logger.error(f"❌ Image conversion failed: {str(e)}, returning original file")
        logger.error(f"📂 Original path exists: {original_path.exists()}")
        # Повертаємо оригінал замість placeholder
        relative_path = f"original/{safe_filename}"
        final_url = f"{MEDIA_URL}{relative_path}"
        logger.info(f"✅ Returning original file: {final_url}")
        return final_url
