"""
Semantic Memory Generator — Phase 2 of Kodara pipeline.

Generates one-line architectural summaries for each module.
Strategy (priority order):
  1. Anthropic Claude Haiku (if ANTHROPIC_API_KEY set)
  2. Heuristic fallback (structure-based, no LLM needed)

Design decision: Heuristic fallback ensures Kodara works offline and
without API keys. AI summaries are an enhancement, not a requirement.
"""

from __future__ import annotations

import os
from typing import Optional


def generate_summaries(
    modules: dict[str, dict],
    api_key: Optional[str] = None,
) -> dict[str, str]:
    """
    Generate semantic summaries for all modules.

    Args:
        modules: dict of {path: module_dict} from the indexer
        api_key: optional Anthropic API key (falls back to env var)

    Returns:
        dict of {path: summary_string}
    """
    key = api_key or os.getenv("ANTHROPIC_API_KEY")
    if key:
        try:
            return _summarize_with_anthropic(modules, key)
        except Exception:
            pass  # Fall through to heuristic

    return _summarize_heuristic(modules)


# ── Heuristic ────────────────────────────────────────────────────────────────


def _summarize_heuristic(modules: dict[str, dict]) -> dict[str, str]:
    """
    Generate summaries from structural metadata — no LLM required.
    Fast, deterministic, works offline.
    """
    summaries: dict[str, str] = {}

    for path, mod in modules.items():
        parts = []

        classes = mod.get("classes", [])
        functions = mod.get("functions", [])
        imports = mod.get("imports", [])
        language = mod.get("language", "")

        if classes:
            names = ", ".join(classes[:3])
            suffix = f" (+{len(classes)-3} more)" if len(classes) > 3 else ""
            parts.append(f"Defines {names}{suffix}")

        if functions:
            pub_fns = [f for f in functions if not f.startswith("_")][:3]
            if pub_fns:
                parts.append(f"Exports: {', '.join(pub_fns)}")

        if imports:
            ext = [i for i in imports if not i.startswith(".")][:3]
            if ext:
                parts.append(f"Uses: {', '.join(ext)}")

        if not parts:
            parts.append(f"{language} module")

        summaries[path] = ". ".join(parts) + "."

    return summaries


# ── Anthropic ─────────────────────────────────────────────────────────────────


def _summarize_with_anthropic(
    modules: dict[str, dict], api_key: str
) -> dict[str, str]:
    """
    Batch-summarize modules via Claude Haiku.
    Processes in batches of 15 to stay within token budgets.
    Falls back to heuristic for any failed batch.
    """
    try:
        import anthropic
    except ImportError:
        return _summarize_heuristic(modules)

    client = anthropic.Anthropic(api_key=api_key)
    summaries: dict[str, str] = {}
    items = list(modules.items())
    batch_size = 15

    for i in range(0, len(items), batch_size):
        batch = items[i : i + batch_size]
        batch_summaries = _process_batch(client, batch)
        summaries.update(batch_summaries)

    return summaries


def _process_batch(client, batch: list[tuple[str, dict]]) -> dict[str, str]:
    """Summarize a single batch of modules via Anthropic."""
    descriptions = []
    for path, mod in batch:
        classes = ", ".join(mod.get("classes", [])[:4]) or "none"
        fns = ", ".join(mod.get("functions", [])[:4]) or "none"
        imports = ", ".join(mod.get("imports", [])[:4]) or "none"
        desc = (
            f"File: {path}\n"
            f"Language: {mod.get('language', '')}\n"
            f"Classes: {classes}\n"
            f"Functions: {fns}\n"
            f"Imports: {imports}"
        )
        descriptions.append(desc)

    prompt = (
        "You are analyzing a codebase architecture. "
        "For each module below, write ONE sentence (max 15 words) describing its architectural responsibility.\n\n"
        + "\n\n".join(
            f"{j+1}. {desc}" for j, desc in enumerate(descriptions)
        )
        + "\n\nRespond with only numbered lines: \"1. <summary>\", \"2. <summary>\", etc."
    )

    try:
        response = client.messages.create(
            model="claude-haiku-4-5-20251001",
            max_tokens=600,
            messages=[{"role": "user", "content": prompt}],
        )
        lines = response.content[0].text.strip().splitlines()
        result: dict[str, str] = {}
        for j, line in enumerate(lines):
            if j >= len(batch):
                break
            text = line.strip()
            if text and text[0].isdigit() and ". " in text:
                text = text.split(". ", 1)[1].strip()
            if text:
                result[batch[j][0]] = text
        return result
    except Exception:
        # Fallback for this batch
        return _summarize_heuristic(dict(batch))
