"""
Stage 3: Stamping — injects a metadata block at the top of each Markdown file.

Reads the Markdown from ``lexi-ml-dev-markdown-files/``, prepends a
``<!-- METADATA_START -->`` … ``<!-- METADATA_END -->`` block, and
overwrites the same blob in-place.
"""

from __future__ import annotations

import logging
from typing import Any

from shared.connectors import blob_manager
from shared.config import BLOB_FOLDER_MARKDOWN
from shared.models import StageResult
from shared.processors.base import PipelineStageBase

logger = logging.getLogger(__name__)

METADATA_START = "<!-- METADATA_START -->"
METADATA_END = "<!-- METADATA_END -->"


def build_metadata_block(doc: dict) -> str:
    """
    Build the Markdown metadata block from document metadata.

    Args:
        doc: Document metadata dict (row from sop_metadata).

    Returns:
        A Markdown string wrapped in METADATA_START / METADATA_END comments.
    """
    title = doc.get("blob_filename") or doc.get("document_name") or ""
    doc_number = doc.get("document_number") or "N/A"
    link = doc.get("url_document_name") or "N/A"

    return (
        f"{METADATA_START}\n"
        f"## Metadata\n\n"
        f"- **Document Name:** {title}\n"
        f"- **Document Number:** {doc_number}\n"
        f"- **Veeva Link:** {link}\n"
        f"{METADATA_END}\n\n"
    )


def stamp_markdown(markdown_text: str, doc: dict) -> str:
    """
    Stamp (or re-stamp) a Markdown string with the metadata block.

    If the text already contains a metadata block it is replaced;
    otherwise the block is prepended.
    """
    new_block = build_metadata_block(doc)

    if METADATA_START in markdown_text and METADATA_END in markdown_text:
        pre = markdown_text.split(METADATA_START)[0]
        post = markdown_text.split(METADATA_END, 1)[1]
        return pre + new_block + post.lstrip()

    return new_block + markdown_text


class StampingStage(PipelineStageBase):
    """Add / update the metadata stamp on the Markdown file in blob storage."""

    stage_name = "STAMPING"

    def execute(self, doc: dict, context: dict[str, Any]) -> StageResult:
        md_blob_path = context.get("markdown_blob_path")
        markdown_text = context.get("markdown_text")

        # If not in context, download from blob
        if not markdown_text:
            if not md_blob_path:
                md_filename = (doc.get("blob_filename", "").rsplit(".", 1)[0]) + ".md"
                md_blob_path = blob_manager.build_blob_path(
                    BLOB_FOLDER_MARKDOWN, md_filename
                )
            markdown_text = blob_manager.download_blob_text(md_blob_path)

        # Stamp
        with self.log.timed("stamp markdown"):
            stamped = stamp_markdown(markdown_text, doc)

        # Upload (overwrite) the stamped markdown
        with self.log.timed("upload stamped markdown"):
            blob_manager.upload_blob(
                md_blob_path, stamped, content_type="text/markdown"
            )

        # Update context for downstream stages
        context["markdown_text"] = stamped
        context["markdown_blob_path"] = md_blob_path

        self.log.info(f"Stamped metadata on '{md_blob_path}'")
        return StageResult(
            stage=self.stage_name, success=True, output_path=md_blob_path
        )
