from __future__ import annotations

import base64
import re
import unicodedata
from typing import Any

from backend.constants import DOCX_MIME_TYPE
from backend.utils.llm_utils import add_completion_msgs

MAX_DOCX_GENERATION_ATTEMPTS = 4
_DOCX_EXTENSION_RE = re.compile(r"\.docx$", re.IGNORECASE)


def execute_llm_completion(project, llm_id: str, messages: list[dict[str, Any]]):
    completion = project.get_llm(llm_id).new_completion()
    add_completion_msgs(completion, messages)
    return completion.execute()


def extract_llm_text(response) -> str:
    if response is None:
        raise ValueError("DOCX generation returned no response")
    if not getattr(response, "success", False):
        raw = getattr(response, "_raw", {}) or {}
        raise ValueError(raw.get("errorMessage") or "DOCX generation failed")
    text = getattr(response, "text", "") or ""
    if not text.strip():
        raise ValueError("DOCX generation returned empty text")
    return text.strip()


def build_docx_filename(
    *, user_prompt: str, requested_filename: str | None = None, document_title: str | None = None
) -> str:
    source = requested_filename or document_title or user_prompt
    source = _DOCX_EXTENSION_RE.sub("", source or "")
    normalized = unicodedata.normalize("NFKD", source).encode("ascii", "ignore").decode("ascii")
    slug = re.sub(r"[^a-z0-9]+", "-", normalized.lower()).strip("-")[:80].strip("-")
    return f"{slug or 'generated-document'}.docx"


def build_inline_docx_artifacts(
    *,
    title: str,
    filename: str,
    docx_bytes: bytes,
    document_yaml: str,
    image_assets: dict[str, dict[str, Any]] | None = None,
    document_metadata: dict[str, Any] | None = None,
) -> list[dict]:
    inline_part = {
        "type": "DATA_INLINE",
        "mimeType": DOCX_MIME_TYPE,
        "dataBase64": base64.b64encode(docx_bytes).decode("ascii"),
        "filename": filename,
        "agentHubGenerationMetadata": {
            "documentYaml": document_yaml,
            **({"imageAssets": image_assets} if image_assets else {}),
        },
    }
    artifact: dict[str, Any] = {
        "name": title or "Document",
        "description": "Generated editable Microsoft Word document",
        "parts": [inline_part],
    }
    if document_metadata:
        artifact["agentHubDocumentMetadata"] = document_metadata
    return [artifact]


def format_retryable_generation_error(error: Exception) -> str:
    return str(error).strip() or error.__class__.__name__
