"""Templates for opencrane init command."""

CONFIG_PY = '''\
from opencrane import OpenCraneConfig
# Uncomment to add custom fence type handlers:
# from opencrane.fences import CodeFenceConfig


class Config(OpenCraneConfig):
    """Project-specific OpenCrane configuration.

    Subclass OpenCraneConfig to register custom fence types,
    chunking strategies, and YAML tree walkers.
    See OpenCraneConfig for all available extension points.
    """

    # Register custom fence types for code blocks in your documentation.
    # The handler receives the fence content and returns a string to embed.
    # fence_types = {
    #     "openapi": CodeFenceConfig(fence_type="openapi", handler=my_openapi_handler),
    #     "json-schema": CodeFenceConfig(fence_type="json-schema", handler=my_schema_handler),
    # }

    # Prepend custom chunking strategies (first match wins).
    # chunking_strategies = [MyTabsStrategy(), *OpenCraneConfig.chunking_strategies]

    # Extend or replace YAML tree walkers for structured YAML chunking.
    # yaml_tree_walkers = [*OpenCraneConfig.yaml_tree_walkers, MyCustomWalker]
'''

SOURCES_YAML = '''\
# OpenCrane source mapping
# Tip: Run `opencrane add` to interactively add sources instead of editing this file.
# Defines repositories and pre-existing llms.txt files to include in the knowledge base.
#
# Each entry maps a source name to its configuration.
#
# GitHub repository example:
# external-sources/my-repo:
#   url: https://github.com/my-org/my-repo
#   docs_path: docs        # subdirectory inside the repo to fetch (empty = root)
#   manual: true           # true = always fetch, false = only if repo has the configured topic
#
# Pre-existing llms.txt example:
# anthropic-docs:
#   type: llmstxt
#   url: https://docs.anthropic.com/llms-full.txt
#   docs_url: https://docs.anthropic.com  # optional, for source links
#   manual: true

sources:
'''

DOCKERFILE = '''\
# syntax=docker/dockerfile:1.4
# Multi-stage build for OpenCrane MCP Server with embedded Milvus Lite
# Optimized for fast rebuilds when only Python code or data changes
# Generated by: opencrane init

# =============================================================================
# Stage 1: Dependencies (cached unless opencrane version changes)
# =============================================================================
FROM python:3.11-slim AS deps

WORKDIR /build

RUN apt-get update && apt-get install -y --no-install-recommends \\
    gcc \\
    g++ \\
    && rm -rf /var/lib/apt/lists/*

RUN --mount=type=cache,target=/root/.cache/pip \\
    pip install opencrane

# =============================================================================
# Stage 2: Model download (cached unless EMBEDDING_MODEL changes)
# =============================================================================
FROM deps AS model

ARG EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5
ENV EMBEDDING_MODEL=${EMBEDDING_MODEL}

RUN --mount=type=cache,target=/root/.cache/huggingface \\
    echo "Downloading embedding model..." && \\
    python3 -c "from sentence_transformers import SentenceTransformer; SentenceTransformer(\'${EMBEDDING_MODEL}\', trust_remote_code=True)" && \\
    mkdir -p /build/hf_cache && cp -r /root/.cache/huggingface /build/hf_cache/

# =============================================================================
# Stage 3: Milvus init (bake vector database into image at build time)
# =============================================================================
FROM deps AS milvus

WORKDIR /build

COPY .opencrane/ ./.opencrane/

ENV MILVUS_DB_PATH=/build/milvus_data/milvus.db
ENV COLLECTION_NAME=opencrane_chunks
ENV DROP_EXISTING=true
ENV PYTHONPATH=/build

RUN mkdir -p /build/milvus_data && opencrane index

# =============================================================================
# Stage 4: Final runtime image
# =============================================================================
FROM python:3.11-slim

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \\
    curl \\
    && rm -rf /var/lib/apt/lists/*

COPY --from=deps /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=deps /usr/local/bin /usr/local/bin

COPY --from=model /build/hf_cache/huggingface /root/.cache/huggingface

COPY --from=milvus /build/milvus_data /app/milvus_data

COPY .opencrane/ /app/.opencrane/

ENV MILVUS_DB_PATH=/app/milvus_data/milvus.db
ENV COLLECTION_NAME=opencrane_chunks
ENV MCP_HTTP_PORT=8000
ENV PYTHONUNBUFFERED=1
ENV TRANSFORMERS_OFFLINE=1

EXPOSE 8000

ENTRYPOINT ["opencrane", "serve", "--transport", "http"]
'''

DOCKER_COMPOSE = '''\
# Generated by: opencrane init
services:
  opencrane-mcp:
    build:
      context: ..
      dockerfile: .opencrane/Dockerfile
      args:
        EMBEDDING_MODEL: "${EMBEDDING_MODEL:-nomic-ai/nomic-embed-text-v1.5}"
    ports:
      - "8000:8000"
    environment:
      MILVUS_DB_PATH: /app/milvus_data/milvus.db
      COLLECTION_NAME: opencrane_chunks
'''

README_MD = '''\
# .opencrane

This directory contains OpenCrane configuration and generated data files.

## Structure

| File | Description | Commit? |
|---|---|---|
| `config.py` | Custom fence types, chunking strategies, tree walkers | Yes |
| `sources.yaml` | Which repos/directories to fetch documentation from | Yes |
| `chunks.json` | Generated document chunks (`opencrane chunk`) | Your choice |
| `embeddings.json` | Generated vector embeddings (`opencrane embed`) | Your choice |

> Committing `chunks.json` and `embeddings.json` is required for Docker image builds via CI/CD.
> For local-only use, you can add them to `.gitignore`.

## Quick Start

```bash
# 1. Add documentation sources interactively
opencrane add

# 2. Build the full pipeline (fetch → llms → chunk → embed → index)
opencrane build

# 3. Start the MCP server (auto-indexes into Milvus Lite)
opencrane serve

# 4. Or launch MCP Inspector for interactive testing
opencrane inspect
```

Run `opencrane serve` and follow the printed instructions to connect your MCP client.

## Docker / Podman

For containerized deployment over HTTP:

```bash
# Build and run
{container_tool}-compose up --build
```

The Docker image bakes the vector database at build time for fast startup.
Configure the embedding model via `EMBEDDING_MODEL` env var in `{container_tool}-compose.yaml`.

## Pipeline Steps

`opencrane build` runs the full pipeline, but each step can be run independently:

| Command | Description |
|---|---|
| `opencrane add` | Interactively add documentation sources |
| `opencrane fetch` | Download documentation from GitHub repositories |
| `opencrane llms` | Generate `llms-full.txt` bundle files |
| `opencrane chunk` | Split documentation into chunks |
| `opencrane embed` | Generate vector embeddings for each chunk |
| `opencrane index` | Load chunks and embeddings into Milvus |
| `opencrane serve` | Start the MCP server (auto-indexes if needed) |
| `opencrane pack` | Package the MCP server for distribution via `uvx` |
| `opencrane inspect` | Launch MCP Inspector web UI for testing |
| `opencrane tokens` | Generate a token count report |

Running steps individually is useful when iterating on a single stage (e.g., re-chunking after config changes without re-fetching).
'''


PACK_MAIN_PY = '''\
"""MCP server with bundled documentation data."""
import os
from pathlib import Path


def main():
    data_dir = Path(__file__).parent / "data"
    os.environ.setdefault("MILVUS_DB_PATH", str(data_dir / "milvus.db"))
    os.environ.setdefault("AI_DOCS_CHUNKS_FILE", str(data_dir / "chunks.json"))
    os.environ.setdefault("METADATA_SCHEMA_PATH", str(data_dir / "metadata-schema.md"))

    import asyncio
    from opencrane.mcp.server import main as serve_main
    asyncio.run(serve_main())


if __name__ == "__main__":
    main()
'''

PACK_PYPROJECT = '''\
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "{name}"
version = "{version}"
description = "MCP server for documentation search — built with OpenCrane"
requires-python = ">=3.11"
dependencies = [
    "opencrane>={opencrane_version}",
]

[project.scripts]
{name} = "{module_name}.__main__:main"

[tool.setuptools.packages.find]
where = ["."]
include = ["{module_name}*"]

[tool.setuptools.package-data]
{module_name} = ["data/**"]
'''

PACK_README = '''\
# {name}

MCP server for documentation search — built with [OpenCrane](https://github.com/opencrane/opencrane).

## Use locally

```bash
claude mcp add {name} -- uvx --from /path/to/{name} {name}
```

## Share via GitHub

Push this directory to a GitHub repository, then others can add it with:

```bash
claude mcp add {name} -- uvx --from "git+https://github.com/you/{name}" {name}
```

## Share via PyPI

Build and upload the wheel:

```bash
pip install build twine
python -m build .
twine upload dist/*
```

Then others can add it with:

```bash
claude mcp add {name} -- uvx {name}
```

> **Note:** PyPI has a 100 MB per-file size limit. If your `milvus.db` exceeds this,
> distribute via GitHub or a direct path instead.

> **Note:** When you re-pack with updated documentation, bump `--version` so that
> `uvx` pulls the new version instead of serving its cache.

## MCP client configuration

### Claude Code

```bash
claude mcp add {name} -- uvx {name}
```

### Cursor / Windsurf / VS Code (mcp.json)

```json
{{
  "mcpServers": {{
    "{name}": {{
      "command": "uvx",
      "args": ["{name}"]
    }}
  }}
}}
```

### Zed (settings.json)

```json
{{
  "context_servers": {{
    "{name}": {{
      "command": {{
        "path": "uvx",
        "args": ["{name}"]
      }}
    }}
  }}
}}
```
'''


def readme(podman: bool = False) -> str:
    tool = "podman" if podman else "docker"
    return README_MD.replace("{container_tool}", tool)
