"""Save session messages as markdown notes."""

from __future__ import annotations

import re
from datetime import UTC
from pathlib import Path

from message_delivery.errors import SaveError
from session_store import SessionMessage


class NoteSaver:
    """Save a SessionMessage as a markdown note under docs/notes/."""

    def build_markdown(self, message: SessionMessage, session_title: str) -> str:
        """Build markdown content from a session message.

        Produces a title heading, a metadata blockquote, a horizontal rule,
        and the message content.
        """
        created = message.created_at
        # ISO 8601 with 'Z' suffix for UTC
        if created.tzinfo is not None:
            created_str = created.astimezone(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
        else:
            created_str = created.strftime("%Y-%m-%dT%H:%M:%SZ")

        lines: list[str] = [
            f"# {session_title}",
            "",
            f"> **Tool:** {message.tool}",
            f"> **Session:** {message.session_id}",
            f"> **Role:** {message.role}",
            f"> **Created:** {created_str}",
            "",
            "---",
            "",
            message.content,
        ]
        return "\n".join(lines)

    def generate_filename(self, message: SessionMessage) -> str:
        """Generate a kebab-case ``.md`` filename from the message content.

        Uses the first non-empty line, strips leading ``#`` heading markers,
        lowercases, replaces whitespace with hyphens, removes non
        ``[a-z0-9-]`` characters, collapses consecutive hyphens, strips
        leading/trailing hyphens, truncates to 60 chars, and appends ``.md``.
        """
        first_line = ""
        for line in message.content.splitlines():
            if line.strip():
                first_line = line.strip()
                break

        # Strip leading '#' characters (markdown headings)
        first_line = first_line.lstrip("#").strip()

        # Convert to lowercase
        first_line = first_line.lower()

        # Replace whitespace sequences with a single hyphen
        first_line = re.sub(r"\s+", "-", first_line)

        # Remove all characters except [a-z0-9-]
        first_line = re.sub(r"[^a-z0-9-]", "", first_line)

        # Collapse consecutive hyphens into one
        first_line = re.sub(r"-+", "-", first_line)

        # Strip leading/trailing hyphens
        first_line = first_line.strip("-")

        # Truncate to 60 characters
        first_line = first_line[:60]

        # Strip trailing hyphen that may result from truncation
        first_line = first_line.rstrip("-")

        return f"{first_line}.md"

    def save(
        self,
        message: SessionMessage,
        session_title: str,
        project_root: Path,
        filename: str | None = None,
    ) -> Path:
        """Write the note to ``<project_root>/docs/notes/<filename>.md``.

        Creates the ``docs/notes/`` directory if it does not exist.
        Returns the path to the written file.  Raises :class:`SaveError`
        on OS errors.
        """
        if filename is None:
            filename = self.generate_filename(message)

        notes_dir = project_root / "docs" / "notes"
        try:
            notes_dir.mkdir(parents=True, exist_ok=True)
            note_path = notes_dir / filename
            markdown = self.build_markdown(message, session_title)
            note_path.write_text(markdown, encoding="utf-8")
        except OSError as exc:
            raise SaveError(f"Failed to save note: {exc}") from exc

        return note_path
