# Copyright (c) 2025 Patrick Motsch
# All rights reserved.

import base64
import logging
from typing import Dict, Any

from modules.datamodels.datamodelChat import ActionResult, ActionDocument
from modules.serviceCenter.services.serviceGeneration.subDocumentUtility import markdownToDocumentJson
from modules.shared.i18nRegistry import normalizePrimaryLanguageTag

logger = logging.getLogger(__name__)


def _persistDocumentsToUserFiles(
    action_documents: list,
    services,
) -> None:
    """Persist file.create output documents to user's file storage (like upload).
    Adds fileId to each document's validationMetadata for download links in UI."""
    mgmt = getattr(services, "interfaceDbComponent", None)
    if not mgmt:
        try:
            import modules.interfaces.interfaceDbManagement as iface
            user = getattr(services, "user", None)
            if not user:
                return
            mgmt = iface.getInterface(
                user,
                mandateId=getattr(services, "mandateId", None) or "",
                featureInstanceId=getattr(services, "featureInstanceId", None) or "",
            )
        except Exception as e:
            logger.warning("file.create: could not get management interface for persistence: %s", e)
            return
    if not mgmt:
        return
    for doc in action_documents:
        try:
            doc_data = doc.documentData if hasattr(doc, "documentData") else doc.get("documentData")
            if not doc_data:
                continue
            if isinstance(doc_data, str):
                content = base64.b64decode(doc_data)
            else:
                content = doc_data
            doc_name = (
                getattr(doc, "documentName", None)
                or doc.get("documentName")
                or "output.pdf"
            )
            mime = (
                getattr(doc, "mimeType", None)
                or doc.get("mimeType")
                or "application/octet-stream"
            )
            file_item = mgmt.createFile(doc_name, mime, content)
            mgmt.createFileData(file_item.id, content)
            meta = getattr(doc, "validationMetadata", None) or doc.get("validationMetadata") or {}
            if isinstance(meta, dict):
                meta["fileId"] = file_item.id
                if hasattr(doc, "validationMetadata"):
                    doc.validationMetadata = meta
                elif isinstance(doc, dict):
                    doc["validationMetadata"] = meta
            logger.info("file.create: persisted %s to user files (id=%s)", doc_name, file_item.id)
        except Exception as e:
            dname = getattr(doc, "documentName", None) or doc.get("documentName", "?")
            logger.warning("file.create: failed to persist document %s: %s", dname, e)


async def create(self, parameters: Dict[str, Any]) -> ActionResult:
    """
    Create a file from context (text/markdown from upstream AI node).
    Uses GenerationService.renderReport to produce docx, pdf, txt, md, html, xlsx, etc.
    """
    context = parameters.get("context", "") or parameters.get("text", "") or ""
    if not isinstance(context, str):
        context = str(context) if context else ""
    context = context.strip()

    if not context:
        return ActionResult.isFailure(error="context is required (connect an AI node or provide text)")

    outputFormat = (parameters.get("outputFormat") or "docx").strip().lower().lstrip(".")
    title = (parameters.get("title") or "Document").strip()
    templateName = parameters.get("templateName")
    language = normalizePrimaryLanguageTag(
        str(parameters.get("language") or "de"),
        "de",
    )

    try:
        structured_content = markdownToDocumentJson(context, title, language)
        if templateName:
            structured_content.setdefault("metadata", {})["templateName"] = templateName

        generation = getattr(self.services, "generation", None)
        if not generation:
            return ActionResult.isFailure(error="Generation service not available")

        ai_service = getattr(self.services, "ai", None)
        rendered_docs = await generation.renderReport(
            extractedContent=structured_content,
            outputFormat=outputFormat,
            language=language,
            title=title,
            userPrompt=None,
            aiService=ai_service,
            parentOperationId=parameters.get("parentOperationId"),
        )

        if not rendered_docs:
            return ActionResult.isFailure(error="Rendering produced no output")

        action_documents = []
        mime_map = {
            "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "pdf": "application/pdf",
            "txt": "text/plain",
            "md": "text/markdown",
            "html": "text/html",
            "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "csv": "text/csv",
            "json": "application/json",
        }
        for rd in rendered_docs:
            doc_data = rd.documentData if hasattr(rd, "documentData") else getattr(rd, "document_data", None)
            doc_name = getattr(rd, "filename", None) or getattr(rd, "documentName", None) or getattr(rd, "document_name", f"output.{outputFormat}")
            mime = getattr(rd, "mimeType", None) or getattr(rd, "mime_type", None) or mime_map.get(outputFormat, "application/octet-stream")

            if isinstance(doc_data, bytes):
                doc_data = base64.b64encode(doc_data).decode("ascii")

            action_documents.append(ActionDocument(
                documentName=doc_name,
                documentData=doc_data,
                mimeType=mime,
                validationMetadata={
                    "actionType": "file.create",
                    "outputFormat": outputFormat,
                    "templateName": templateName,
                },
            ))

        _persistDocumentsToUserFiles(action_documents, self.services)
        return ActionResult.isSuccess(documents=action_documents)

    except Exception as e:
        logger.error(f"file.create failed: {e}", exc_info=True)
        return ActionResult.isFailure(error=str(e))
