"""Indexer — Generate INDEX.md with module summaries."""

import os
import requests
from typing import List, Optional
from datetime import datetime

from .splitter import Module


def generate_index(
    modules: List[Module],
    original_file: str = "MEMORY.md",
    provider: str = "anthropic",
    model: Optional[str] = None,
    api_key: Optional[str] = None,
    base_url: Optional[str] = None,
    include_summaries: bool = True,
) -> str:
    """
    Generate INDEX.md content with module summaries.
    
    Args:
        modules: List of modules to index
        original_file: Name of the original file that was modulized
        provider: LLM provider for generating summaries
        model: Model name
        api_key: API key
        base_url: Base URL for compatible providers
        include_summaries: Whether to generate LLM summaries (False = headers only)
        
    Returns:
        INDEX.md content as string
    """
    lines = [
        "# Memory Index",
        "",
        f"*Auto-generated by soul.py modulizer on {datetime.now().strftime('%Y-%m-%d %H:%M')}*",
        f"*Source: {original_file}*",
        "",
        "---",
        "",
    ]
    
    # Stats
    total_chunks = sum(m.chunk_count for m in modules)
    total_size = sum(m.size_kb for m in modules)
    lines.append(f"**{len(modules)} modules** · {total_chunks} sections · {total_size:.1f} KB total")
    lines.append("")
    lines.append("---")
    lines.append("")
    
    # Module listing
    lines.append("## Modules")
    lines.append("")
    
    for module in sorted(modules, key=lambda m: m.name):
        lines.append(f"### [{module.category.title()}]({module.name})")
        lines.append(f"*{module.chunk_count} sections · {module.size_kb:.1f} KB*")
        lines.append("")
        
        if include_summaries:
            summary = _generate_summary(module, provider, model, api_key, base_url)
            lines.append(summary)
        else:
            # Just list the headers
            for cc in module.chunks[:5]:  # First 5 headers
                lines.append(f"- {cc.chunk.header}")
            if module.chunk_count > 5:
                lines.append(f"- *... and {module.chunk_count - 5} more*")
        
        lines.append("")
    
    # Quick reference
    lines.append("---")
    lines.append("")
    lines.append("## Quick Reference")
    lines.append("")
    lines.append("| Module | Category | Sections | Size |")
    lines.append("|--------|----------|----------|------|")
    for module in sorted(modules, key=lambda m: m.name):
        lines.append(f"| [{module.name}]({module.name}) | {module.category} | {module.chunk_count} | {module.size_kb:.1f} KB |")
    
    lines.append("")
    lines.append("---")
    lines.append("")
    lines.append("*To retrieve: Read this index, identify relevant module(s), then read those files.*")
    
    return '\n'.join(lines)


def _generate_summary(
    module: Module,
    provider: str,
    model: Optional[str],
    api_key: Optional[str],
    base_url: Optional[str],
) -> str:
    """Generate a brief summary of module contents using LLM."""
    
    # Truncate content for summary prompt
    content_preview = module.content[:2000]
    if len(module.content) > 2000:
        content_preview += "\n...(truncated)"
    
    prompt = f"""Summarize this module in 1-2 sentences. Focus on what topics/information it contains.

Module: {module.category}
Content:
{content_preview}

Summary (1-2 sentences):"""

    try:
        if provider == "anthropic":
            summary = _call_anthropic(prompt, model, api_key)
        elif provider in ("openai", "openai-compatible"):
            summary = _call_openai(prompt, model, api_key, base_url)
        elif provider == "gemini":
            summary = _call_gemini(prompt, model, api_key)
        else:
            return _fallback_summary(module)
        
        return summary.strip()
    except Exception:
        return _fallback_summary(module)


def _fallback_summary(module: Module) -> str:
    """Generate a simple summary without LLM."""
    headers = [cc.chunk.header for cc in module.chunks[:3]]
    return f"Contains: {', '.join(headers)}" + (" and more..." if module.chunk_count > 3 else "")


def _call_anthropic(prompt: str, model: Optional[str], api_key: Optional[str]) -> str:
    api_key = api_key or os.environ.get("ANTHROPIC_API_KEY")
    model = model or "claude-sonnet-4-20250514"
    
    response = requests.post(
        "https://api.anthropic.com/v1/messages",
        headers={
            "x-api-key": api_key,
            "anthropic-version": "2023-06-01",
            "content-type": "application/json",
        },
        json={
            "model": model,
            "max_tokens": 200,
            "messages": [{"role": "user", "content": prompt}],
        },
        timeout=30,
    )
    response.raise_for_status()
    return response.json()["content"][0]["text"]


def _call_openai(prompt: str, model: Optional[str], api_key: Optional[str], base_url: Optional[str]) -> str:
    api_key = api_key or os.environ.get("OPENAI_API_KEY")
    base_url = base_url or "https://api.openai.com/v1"
    model = model or "gpt-4o-mini"
    
    response = requests.post(
        f"{base_url}/chat/completions",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json={
            "model": model,
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 200,
        },
        timeout=30,
    )
    response.raise_for_status()
    return response.json()["choices"][0]["message"]["content"]


def _call_gemini(prompt: str, model: Optional[str], api_key: Optional[str]) -> str:
    api_key = api_key or os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")
    model = model or "gemini-2.0-flash"
    
    response = requests.post(
        f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent",
        headers={"Content-Type": "application/json"},
        params={"key": api_key},
        json={"contents": [{"parts": [{"text": prompt}]}]},
        timeout=30,
    )
    response.raise_for_status()
    return response.json()["candidates"][0]["content"]["parts"][0]["text"]
