from __future__ import annotations

from backend.services.artifact_models import PreparedToolSourceArtifact
from backend.services.pptx_artifact_generation.image_assets import build_image_assets_prompt_section
from backend.services.pptx_artifact_generation.models import PptxImageAsset


def add_source_artifacts_to_pptx_prompt(
    query: str,
    source_artifacts: list[PreparedToolSourceArtifact],
    image_assets: list[PptxImageAsset] | None = None,
) -> str:
    """Append only deck-relevant source content to the PPTX prompt.

    This is the LLM-facing view of selected source artifacts: it keeps the useful artifact content and omits DSS
    storage identifiers or other backend-only tracing fields.
    """

    if not source_artifacts:
        return query

    lines = [
        query.strip(),
        "",
        "Source artifact context:",
        "Use the following referenced artifact content as source material for the deck when relevant.",
        "Prefer the referenced artifact data for facts/tables and the referenced images for visuals, instead of inventing them.",
    ]

    for source_artifact in source_artifacts:
        lines.extend(_format_source_artifact_for_prompt(source_artifact))
    image_assets_section = build_image_assets_prompt_section(image_assets or [])
    if image_assets_section:
        lines.extend(["", image_assets_section])

    return "\n".join(lines).strip()


def build_pptx_source_artifact_user_message(
    query: str,
    source_artifacts: list[PreparedToolSourceArtifact],
    image_assets: list[PptxImageAsset] | None = None,
) -> dict[str, object]:
    """Build the multimodal user message consumed by deck generation.

    The text part carries normalized artifact summaries plus the deck-local image asset registry. Any usable
    `IMAGE_INLINE` parts are then attached verbatim so a multimodal model can inspect the visuals directly.
    These parts are forwarded as-is into the DSS multipart completion payload and ingested directly by the LLM.
    """
    parts = _build_pptx_multimodal_parts(
        text=add_source_artifacts_to_pptx_prompt(query, source_artifacts, image_assets),
        image_assets=image_assets or [],
    )
    return {"role": "user", "parts": parts}


def build_pptx_tool_user_message(
    *,
    query: str,
    conversation_context_section: str,
    source_artifacts: list[PreparedToolSourceArtifact],
    image_assets: list[PptxImageAsset],
) -> dict[str, object] | None:
    """Prepend the conversation context to the query, then delegate to the matching source-material builder.

    Returns None when there is nothing to add, so the generation service keeps using the plain prompt.
    """

    if not (conversation_context_section.strip() or source_artifacts or image_assets):
        return None
    text = "\n\n".join(part for part in (query.strip(), conversation_context_section.strip()) if part)
    if source_artifacts:
        return build_pptx_source_artifact_user_message(text, source_artifacts, image_assets)
    return build_pptx_image_assets_user_message(text, image_assets)


def build_pptx_image_assets_user_message(query: str, image_assets: list[PptxImageAsset]) -> dict[str, object]:
    """Build a multimodal user message when the only source context is the resolved image registry."""

    text = "\n".join([query.strip(), "", build_image_assets_prompt_section(image_assets)]).strip()
    return {"role": "user", "parts": _build_pptx_multimodal_parts(text=text, image_assets=image_assets)}


def _build_pptx_multimodal_parts(text: str, image_assets: list[PptxImageAsset]) -> list[dict[str, str]]:
    parts: list[dict[str, str]] = [{"type": "TEXT", "text": text}]
    for index, image_asset in enumerate(image_assets, start=1):
        label = image_asset.artifact_name or f"Image {index}"
        parts.extend(
            [
                {
                    "type": "TEXT",
                    "text": (
                        f"Attached source image {index}: asset_id={image_asset.asset_id}; label={label}. "
                        f"When using this visual in deck YAML, reference asset_id `{image_asset.asset_id}`."
                    ),
                },
                {
                    "type": "IMAGE_INLINE",
                    "inlineImage": image_asset.data_base64,
                    "imageMimeType": image_asset.mime_type,
                },
            ]
        )
    return parts


def _format_source_artifact_for_prompt(source_artifact: PreparedToolSourceArtifact) -> list[str]:
    """Render one prepared source artifact as a compact LLM-facing content block."""

    lines = [
        f"- Referenced artifact: {source_artifact.artifact_name or 'Artifact'}",
        "  content:",
    ]
    lines.extend(f"    {line}" for line in (source_artifact.content or "").splitlines())
    return lines
