import os
import uuid
import json
import re

from PIL import Image


SUPPORTED_FORMATS = {"jpg", "jpeg", "png", "svg"}

FORMAT_MAP = {
    "jpg": "JPEG",
    "jpeg": "JPEG",
    "png": "PNG",
}


def _parse_url_entry(url_entry):
    if isinstance(url_entry, str):
        try:
            parsed = json.loads(url_entry)
            if isinstance(parsed, dict):
                return parsed.get("path", "")
        except (json.JSONDecodeError, TypeError):
            return url_entry
    elif isinstance(url_entry, dict):
        return url_entry.get("path", "")
    return ""


def _minify_svg(content):
    content = re.sub(r'<!--.*?-->', '', content, flags=re.DOTALL)
    content = re.sub(r'>\s+<', '><', content)
    content = re.sub(r'\s+', ' ', content)
    content = content.strip()
    return content


def _compress_image(input_path, output_path, ext):
    ext_lower = ext.lower().lstrip(".")

    if ext_lower == "svg":
        with open(input_path, "r", encoding="utf-8", errors="ignore") as f:
            svg_content = f.read()
        minified = _minify_svg(svg_content)
        with open(output_path, "w", encoding="utf-8") as f:
            f.write(minified)
        return True

    pil_format = FORMAT_MAP.get(ext_lower)
    if not pil_format:
        return False

    img = Image.open(input_path)

    if ext_lower in ("jpg", "jpeg"):
        if img.mode in ("RGBA", "P"):
            img = img.convert("RGB")
        img.save(output_path, format="JPEG", quality=75, optimize=True)
    elif ext_lower == "png":
        if img.mode == "RGBA":
            img = img.quantize(colors=256, method=Image.Quantize.MEDIANCUT, dither=Image.Dither.FLOYDSTEINBERG).convert("RGBA")
        elif img.mode != "P":
            img = img.quantize(colors=256, method=Image.Quantize.MEDIANCUT, dither=Image.Dither.FLOYDSTEINBERG)
        img.save(output_path, format="PNG", optimize=True)

    img.close()
    return True


def convert(urls, target_format, options, config):
    upload_dir = config.get("UPLOAD_DIR", "static/uploads")
    results = []
    errors = []

    for url_entry in urls:
        file_path = _parse_url_entry(url_entry)
        if not file_path or file_path == "empty":
            continue

        try:
            full_path = os.path.join(upload_dir, file_path)
            if not os.path.exists(full_path):
                full_path = file_path
            if not os.path.exists(full_path):
                errors.append(f"File not found: {os.path.basename(file_path)}")
                continue

            filename = os.path.basename(full_path)
            name, ext = os.path.splitext(filename)
            ext_lower = ext.lower().lstrip(".")

            if ext_lower not in SUPPORTED_FORMATS:
                errors.append(f"Unsupported format: {ext_lower}")
                continue

            out_dir = os.path.join(upload_dir, uuid.uuid4().hex)
            os.makedirs(out_dir, exist_ok=True)

            output_file = os.path.join(out_dir, f"{name}{ext}")

            success = _compress_image(full_path, output_file, ext_lower)
            if not success:
                errors.append(f"Failed to compress {filename}")
                continue

            results.append(output_file)

        except Exception as e:
            fname = os.path.basename(file_path) if file_path else "unknown"
            errors.append(f"Failed to compress {fname}: {str(e)}")

    if not results and errors:
        return {"error": True, "message": "; ".join(errors)}

    if not results and not errors:
        return {"error": True, "message": "No files were provided for compression."}

    return {
        "error": False,
        "results": results,
        "output_path": results[0] if results else "",
        "errors": errors if errors else None
    }
