"""
ShelfAI Indexer Agent.

Generates one-line abstracts for shelf files using an LLM.
Abstracts are optimized for retrieval — they describe when and why
an agent should load each file, not just what it contains.
"""

from pathlib import Path
from typing import Optional

from shelfai.core.shelf import Shelf
from shelfai.providers import LLMProvider
from shelfai.prompts import INDEXER_SYSTEM_PROMPT, INDEXER_USER_PROMPT


class IndexerAgent:
    """
    Generates and updates abstracts in the shelf index.

    The indexer reads each shelf file and uses an LLM to write a
    one-line abstract optimized for agent retrieval. Optionally
    accepts additional context (e.g. a workflow description) to
    make abstracts more domain-specific.
    """

    def __init__(self, shelf: Shelf, provider: LLMProvider):
        """
        Initialize the indexer.

        Args:
            shelf: Shelf instance to index
            provider: LLM provider for abstract generation
        """
        self.shelf = shelf
        self.provider = provider

    def index_file(
        self,
        file_path: str,
        context: Optional[str] = None,
    ) -> str:
        """
        Generate an abstract for a single shelf file.

        Args:
            file_path: Relative path to the shelf file
            context: Optional additional context for domain-specific abstracts

        Returns:
            Generated abstract string
        """
        content = self.shelf.read_file(file_path)

        context_section = ""
        if context:
            context_section = (
                f"## Additional Context\n"
                f"This abstract should be optimized for the following workflow:\n"
                f"{context}"
            )

        user_prompt = INDEXER_USER_PROMPT.format(
            file_path=file_path,
            file_content=content[:8000],  # Truncate very long files
            context_section=context_section,
        )

        abstract = self.provider.complete(
            system=INDEXER_SYSTEM_PROMPT,
            user=user_prompt,
            max_tokens=500,
        )

        # Clean up the response
        abstract = abstract.strip().strip('"').strip("'")

        # Enforce max length from config
        config = self.shelf.load_config()
        max_len = config.index.max_abstract_length
        if len(abstract) > max_len:
            abstract = abstract[: max_len - 3] + "..."

        return abstract

    def index_all(
        self,
        context: Optional[str] = None,
        force: bool = False,
    ) -> dict:
        """
        Index all shelf files, generating abstracts for new or modified files.

        Args:
            context: Optional additional context for domain-specific abstracts
            force: If True, regenerate all abstracts even if unchanged

        Returns:
            Dict with keys: generated (list), unchanged (list), errors (list)
        """
        result = {"generated": [], "unchanged": [], "errors": []}

        files = self.shelf.list_files()
        index = self.shelf.index

        for file_path in files:
            # Skip if already indexed and not forced
            existing = index.get(file_path)
            if existing and not force:
                result["unchanged"].append(file_path)
                continue

            try:
                abstract = self.index_file(file_path, context=context)

                # Determine category from path
                parts = Path(file_path).parts
                category = parts[0].title() if len(parts) > 1 else "Uncategorized"

                index.add(file_path, abstract, category)
                result["generated"].append({"file": file_path, "abstract": abstract})

            except Exception as e:
                result["errors"].append({"file": file_path, "error": str(e)})

        return result
