import base64
import os
import re
import sys
from pathlib import Path

from dotenv import load_dotenv
load_dotenv(Path(__file__).parent / ".env")

from markitdown._base_converter import DocumentConverter

_DESCRIBE_PROMPT = (
    "Describe the content of this image accurately (all text must be verbatim) and concisely."
)

LLM_BASE_URL = os.getenv("LLM_BASE_URL", "http://localhost:8500/v1")
LLM_API_KEY = os.getenv("LLM_API_KEY", "none")
LLM_MODEL = os.getenv("LLM_MODEL", "Qwen3.6-35B-A3B-UD-IQ2_XXS.gguf")


def default_llm_client():
    import openai
    return openai.OpenAI(base_url=LLM_BASE_URL, api_key=LLM_API_KEY)


def sanitize_alt_text(text: str) -> str:
    """Make arbitrary text safe to embed as markdown image alt text."""
    text = (text.replace("[", "(").replace("]", ")")
                .replace('"', "'").replace("$", r"\$")
                .replace("<", "(").replace(">", ")")
                .replace("|", " "))
    text = text.replace("\r\n", " ").replace("\r", " ").replace("\n", " ")
    # A trailing bolded number (e.g. "**12**") makes Obsidian read it as an
    # image width; unwrap just that token, keep bold elsewhere.
    return re.sub(r"\*+(\d+(?:x\d+)?)\*+\s*$", r"\1", text)


class VLMBase(DocumentConverter):
    """Base class providing shared LLM image description for converters."""

    def __init__(self, llm_client=None, llm_model: str = LLM_MODEL):
        self._llm_client = llm_client or default_llm_client()
        self._llm_model = llm_model

    def _describe(self, img_path: Path, client, model: str, prompt: str = _DESCRIBE_PROMPT) -> str | None:
        suffix = img_path.suffix.lower()
        mime = "image/png" if suffix == ".png" else "image/jpeg"
        data = base64.b64encode(img_path.read_bytes()).decode()
        try:
            response = client.chat.completions.create(
                model=model,
                messages=[{
                    "role": "user",
                    "content": [
                        {"type": "text", "text": prompt},
                        {"type": "image_url", "image_url": {"url": f"data:{mime};base64,{data}"}},
                    ],
                }],
            )
            text = response.choices[0].message.content.strip()
            return sanitize_alt_text(text)
        except Exception as e:
            print(f"LLM error on {img_path.name}: {e}", file=sys.stderr)
            return None
