"""Document store — Markdown-based document management for agent-owned documents."""

from __future__ import annotations

import logging
from datetime import UTC, datetime
from pathlib import Path

logger = logging.getLogger(__name__)


class DocumentStore:
    """
    Manages agent-owned Markdown documents.

    Documents are organized as: docs/{agent_id}/{document-name}.md
    Each document has a YAML frontmatter header with metadata.
    """

    def __init__(self, docs_dir: Path) -> None:
        self.docs_dir = docs_dir

    def initialize(self) -> None:
        """Ensure the docs directory exists."""
        self.docs_dir.mkdir(parents=True, exist_ok=True)
        logger.info("DocumentStore initialized at %s", self.docs_dir)

    def read(self, doc_path: str) -> str:
        """Read a document by relative path (e.g., 'liam/daily-task-flow.md')."""
        full_path = self.docs_dir / doc_path
        if not full_path.exists():
            return f"Document not found: {doc_path}"
        return full_path.read_text(encoding="utf-8")

    def write(self, doc_path: str, content: str, author: str) -> None:
        """Write/update a document, adding frontmatter if not present."""
        full_path = self.docs_dir / doc_path
        full_path.parent.mkdir(parents=True, exist_ok=True)

        # Add frontmatter if the content doesn't already have it
        if not content.startswith("---"):
            now = datetime.now(UTC).isoformat()
            frontmatter = f"---\nauthor: {author}\nupdated: {now}\n---\n\n"
            content = frontmatter + content

        full_path.write_text(content, encoding="utf-8")
        logger.info("Document written: %s by %s", doc_path, author)

    def exists(self, doc_path: str) -> bool:
        """Check if a document exists."""
        return (self.docs_dir / doc_path).exists()

    def list_docs(self, agent_id: str | None = None, exclude_archive: bool = True) -> list[str]:
        """List all documents, optionally filtered by agent (subdirectory).

        By default, files inside an ``archive/`` subfolder are excluded so that
        completed project documents don't clutter the agent's active context.
        """
        if agent_id:
            search_dir = self.docs_dir / agent_id
            if not search_dir.exists():
                return []
            results: list[str] = []
            for f in search_dir.glob("*.md"):
                results.append(f"{agent_id}/{f.name}")
            # Also pick up files in non-archive subdirectories
            for f in search_dir.rglob("*.md"):
                if f.parent == search_dir:
                    continue  # already captured above
                rel = f.relative_to(search_dir)
                if exclude_archive and rel.parts[0].lower() == "archive":
                    continue
                results.append(f"{agent_id}/{rel.as_posix()}")
            return sorted(set(results))
        else:
            results = []
            for f in self.docs_dir.rglob("*.md"):
                rel = f.relative_to(self.docs_dir)
                if exclude_archive and "archive" in [p.lower() for p in rel.parts[:-1]]:
                    continue
                results.append(str(rel))
            return sorted(results)

    def delete(self, doc_path: str) -> bool:
        """Delete a document. Returns True if deleted, False if not found."""
        full_path = self.docs_dir / doc_path
        if full_path.exists():
            full_path.unlink()
            logger.info("Document deleted: %s", doc_path)
            return True
        return False

    def get_agent_docs_summary(self, agent_id: str) -> str:
        """Get a summary of all documents owned by an agent."""
        docs = self.list_docs(agent_id)
        if not docs:
            return f"No documents found for agent: {agent_id}"

        lines = [f"## Documents owned by {agent_id}\n"]
        for doc_path in docs:
            content = self.read(doc_path)
            # Extract first heading or first line as title
            first_line = ""
            for line in content.split("\n"):
                stripped = line.strip()
                if stripped and not stripped.startswith("---"):
                    first_line = stripped.lstrip("#").strip()
                    break
            lines.append(f"- **{doc_path}**: {first_line[:100]}")

        return "\n".join(lines)
