from __future__ import annotations

import json
from typing import Any, Dict, List


def to_data_url(image_str: str) -> str:
    if not isinstance(image_str, str) or not image_str:
        return image_str
    s = image_str.strip()
    if s.startswith("data:image/"):
        return s
    if s.startswith("http://") or s.startswith("https://"):
        return s
    b64 = s.replace("\n", "").replace("\r", "")
    kind = "image/png"
    if b64.startswith("/9j/"):
        kind = "image/jpeg"
    elif b64.startswith("iVBORw0KGgo"):
        kind = "image/png"
    elif b64.startswith("R0lGOD"):
        kind = "image/gif"
    return f"data:{kind};base64,{b64}"


def convert_ollama_messages(
    messages: List[Dict[str, Any]] | None, top_images: List[str] | None
) -> List[Dict[str, Any]]:
    out: List[Dict[str, Any]] = []
    msgs = messages if isinstance(messages, list) else []
    pending_call_ids: List[str] = []
    call_counter = 0
    for m in msgs:
        if not isinstance(m, dict):
            continue
        role = m.get("role") or "user"
        nm: Dict[str, Any] = {"role": role}

        content = m.get("content")
        images = m.get("images") if isinstance(m.get("images"), list) else []
        parts: List[Dict[str, Any]] = []
        if isinstance(content, list):
            for p in content:
                if isinstance(p, dict) and p.get("type") == "text" and isinstance(p.get("text"), str):
                    parts.append({"type": "text", "text": p.get("text")})
        elif isinstance(content, str):
            parts.append({"type": "text", "text": content})
        for img in images:
            url = to_data_url(img)
            if isinstance(url, str) and url:
                parts.append({"type": "image_url", "image_url": {"url": url}})
        if parts:
            nm["content"] = parts

        if role == "assistant" and isinstance(m.get("tool_calls"), list):
            tcs = []
            for tc in m.get("tool_calls"):
                if not isinstance(tc, dict):
                    continue
                fn = tc.get("function") if isinstance(tc.get("function"), dict) else {}
                name = fn.get("name") if isinstance(fn.get("name"), str) else None
                args = fn.get("arguments")
                if name is None:
                    continue
                call_id = tc.get("id") or tc.get("call_id")
                if not isinstance(call_id, str) or not call_id:
                    call_counter += 1
                    call_id = f"ollama_call_{call_counter}"
                pending_call_ids.append(call_id)
                tcs.append(
                    {
                        "id": call_id,
                        "type": "function",
                        "function": {
                            "name": name,
                            "arguments": args if isinstance(args, str) else (json.dumps(args) if isinstance(args, dict) else "{}"),
                        },
                    }
                )
            if tcs:
                nm["tool_calls"] = tcs

        if role == "tool":
            tci = m.get("tool_call_id") or m.get("id")
            if not isinstance(tci, str) or not tci:
                if pending_call_ids:
                    tci = pending_call_ids.pop(0)
            if isinstance(tci, str) and tci:
                nm["tool_call_id"] = tci

            if not parts and isinstance(content, str):
                nm["content"] = content

        out.append(nm)

    if isinstance(top_images, list) and top_images:
        attach_to = None
        for i in range(len(out) - 1, -1, -1):
            if out[i].get("role") == "user":
                attach_to = out[i]
                break
        if attach_to is None:
            attach_to = {"role": "user", "content": []}
            out.append(attach_to)
        attach_to.setdefault("content", [])
        for img in top_images:
            url = to_data_url(img)
            if isinstance(url, str) and url:
                attach_to["content"].append({"type": "image_url", "image_url": {"url": url}})
    return out


def normalize_ollama_tools(tools: List[Dict[str, Any]] | None) -> List[Dict[str, Any]]:
    out: List[Dict[str, Any]] = []
    if not isinstance(tools, list):
        return out
    for t in tools:
        if not isinstance(t, dict):
            continue
        if isinstance(t.get("function"), dict):
            fn = t.get("function")
            name = fn.get("name") if isinstance(fn.get("name"), str) else None
            if not name:
                continue
            out.append(
                {
                    "type": "function",
                    "function": {
                        "name": name,
                        "description": fn.get("description") or "",
                        "parameters": fn.get("parameters") if isinstance(fn.get("parameters"), dict) else {"type": "object", "properties": {}},
                    },
                }
            )
            continue
        name = t.get("name") if isinstance(t.get("name"), str) else None
        if name:
            out.append(
                {
                    "type": "function",
                    "function": {
                        "name": name,
                        "description": t.get("description") or "",
                        "parameters": {"type": "object", "properties": {}},
                    },
                }
            )
    return out
