"""Command template configuration CRUD API routes.

Template content is stored in CommandTemplateSlot child rows (one per slot_name).
Slot names correspond to command names (e.g. 'status', 'help', 'albums').
"""

import logging
from typing import Any

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession

from ..auth.dependencies import get_current_user
from ..database.engine import get_session
from ..database.models import CommandTemplateConfig, CommandTemplateSlot, User
from .slot_helpers import load_slots, render_template_preview, save_slots

_LOGGER = logging.getLogger(__name__)

router = APIRouter(prefix="/api/command-template-configs", tags=["command-template-configs"])


class CommandTemplateConfigCreate(BaseModel):
    provider_type: str
    name: str
    description: str | None = None
    icon: str | None = None
    slots: dict[str, dict[str, str]] = {}  # slot_name -> {locale -> template}


class CommandTemplateConfigUpdate(BaseModel):
    name: str | None = None
    description: str | None = None
    icon: str | None = None
    slots: dict[str, dict[str, str]] | None = None


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

async def _load_slots(session: AsyncSession, config_id: int) -> dict[str, dict[str, str]]:
    return await load_slots(session, CommandTemplateSlot, config_id)


async def _save_slots(session: AsyncSession, config_id: int, slots: dict[str, dict[str, str]]) -> None:
    await save_slots(session, CommandTemplateSlot, config_id, slots)


async def _response(session: AsyncSession, c: CommandTemplateConfig) -> dict[str, Any]:
    slots = await _load_slots(session, c.id)
    return {
        "id": c.id,
        "user_id": c.user_id,
        "provider_type": c.provider_type,
        "name": c.name,
        "description": c.description,
        "icon": c.icon,
        "slots": slots,
        "created_at": c.created_at.isoformat(),
    }


async def _get(session: AsyncSession, config_id: int, user_id: int) -> CommandTemplateConfig:
    config = await session.get(CommandTemplateConfig, config_id)
    if not config or (config.user_id != user_id and config.user_id != 0):
        raise HTTPException(status_code=404, detail="Command template config not found")
    return config


# ---------------------------------------------------------------------------
# Routes
# ---------------------------------------------------------------------------

@router.get("/defaults")
async def get_default_command_templates(
    provider_type: str,
    slot_name: str | None = None,
    locale: str | None = None,
    user: User = Depends(get_current_user),
):
    """Return the shipped Jinja2 default command templates for a provider type.

    Used by the UI's "Reset to default" actions. Filtering works the same way
    as the notification-template equivalent: omit ``slot_name`` for the whole
    set, omit ``locale`` for every locale.

    Response shape: ``{slot_name: {locale: template_text}}``
    """
    from notify_bridge_core.templates.command_defaults.loader import (
        load_default_command_templates,
    )
    from notify_bridge_core.templates.defaults.loader import get_available_locales
    locales = [locale] if locale else get_available_locales()
    result: dict[str, dict[str, str]] = {}
    for loc in locales:
        defaults = load_default_command_templates(loc, provider_type)
        for name, text in defaults.items():
            if slot_name and name != slot_name:
                continue
            result.setdefault(name, {})[loc] = text
    return result


@router.get("/variables")
async def get_command_variables(
    user: User = Depends(get_current_user),
):
    """Get variable reference for each command template slot."""
    common_vars = {
        "locale": "Current locale (en/ru)",
    }
    asset_fields = {
        "id": "Asset ID (UUID)",
        "filename": "Original filename (preferred; same as originalFileName)",
        "originalFileName": "Original filename (alias of filename, kept for backward-compat with older templates)",
        "type": "IMAGE or VIDEO",
        "created_at": "Creation date/time (ISO 8601)",
        "createdAt": "Creation date/time (alias of created_at)",
        "year": "Year of the memory (memory command only)",
        "public_url": "Per-asset public share URL (empty if no album link)",
        "city": "City name (empty if unknown)",
        "country": "Country name (empty if unknown)",
        "is_favorite": "Whether asset is favorited (boolean)",
    }
    album_fields = {
        "name": "Album name",
        "id": "Album ID (UUID)",
        "public_url": "Public share link URL (empty if none)",
        "asset_count": "Number of assets in the album",
        "photo_count": "Number of photos in the album",
        "video_count": "Number of videos in the album",
        "shared": "Whether the album is shared (boolean)",
        "owner": "Album owner display name",
    }
    command_fields = {
        "name": "Command name (e.g. status, albums)",
        "description": "Command description text",
        "usage": "Usage example (e.g. /search sunset) — only for commands that take arguments",
    }
    event_fields = {
        "type": "Event type (assets_added, assets_removed, etc.)",
        "album": "Album/collection name",
        "count": "Number of affected assets",
        "date": "Event date/time string (MM/DD HH:MM)",
    }

    assets_slot = lambda desc: {
        "description": desc,
        "variables": {**common_vars, "assets": "List of asset dicts (use {% for asset in assets %})", "count": "Number of results"},
        "asset_fields": asset_fields,
    }

    # --- Shared slots (all providers) ---
    shared = {
        "start": {
            "description": "/start greeting message",
            "variables": {**common_vars, "bot_name": "Bot display name"},
        },
        "help": {
            "description": "/help command listing",
            "variables": {**common_vars, "commands": "List of command dicts (use {% for cmd in commands %})"},
            "command_fields": command_fields,
        },
        "rate_limited": {
            "description": "Rate limit warning message",
            "variables": {**common_vars, "wait": "Seconds to wait before retry"},
        },
        "no_results": {
            "description": "Empty results fallback",
            "variables": {**common_vars, "command": "Command name", "query": "Search query (empty for non-search commands)"},
        },
        "desc_help": {"description": "Description for /help command", "variables": common_vars},
        "desc_status": {"description": "Description for /status command", "variables": common_vars},
    }

    # --- Immich-specific ---
    immich = {
        "status": {
            "description": "/status tracker summary (scoped to this chat)",
            "variables": {
                **common_vars,
                "total_albums": "Tracked albums visible to this chat",
                "last_event": "Last event timestamp string (scoped to this chat's albums)",
            },
        },
        "albums": {
            "description": "/albums tracked albums list",
            "variables": {**common_vars, "albums": "List of album dicts (use {% for album in albums %})"},
            "album_fields": album_fields,
        },
        "events": {
            "description": "/events recent events",
            "variables": {**common_vars, "events": "List of event dicts (use {% for event in events %})"},
            "event_fields": event_fields,
        },
        "people": {
            "description": "/people detected people",
            "variables": {**common_vars, "people": "List of name strings (use {% for name in people %})"},
        },
        "search": {
            **assets_slot("/search, /find, /person, /place results"),
            "variables": {**common_vars, "assets": "List of asset dicts (use {% for asset in assets %})", "query": "Search query", "command": "Actual command name (search/find/person/place)", "count": "Number of results"},
        },
        "latest": assets_slot("/latest recent photos"),
        "favorites": assets_slot("/favorites starred items"),
        "random": assets_slot("/random random photos"),
        "summary": {
            "description": "/summary album summary",
            "variables": {**common_vars, "albums": "List of album dicts (use {% for album in albums %})"},
            "album_fields": album_fields,
        },
        "memory": {
            "description": "/memory On This Day photos",
            "variables": {**common_vars, "assets": "List of asset dicts with year field (use {% for asset in assets %})", "count": "Number of results"},
            "asset_fields": asset_fields,
        },
        "desc_albums": {"description": "Description for /albums command", "variables": common_vars},
        "desc_events": {"description": "Description for /events command", "variables": common_vars},
        "desc_summary": {"description": "Description for /summary command", "variables": common_vars},
        "desc_latest": {"description": "Description for /latest command", "variables": common_vars},
        "desc_memory": {"description": "Description for /memory command", "variables": common_vars},
        "desc_random": {"description": "Description for /random command", "variables": common_vars},
        "desc_search": {"description": "Description for /search command", "variables": common_vars},
        "desc_find": {"description": "Description for /find command", "variables": common_vars},
        "desc_person": {"description": "Description for /person command", "variables": common_vars},
        "desc_place": {"description": "Description for /place command", "variables": common_vars},
        "desc_favorites": {"description": "Description for /favorites command", "variables": common_vars},
        "desc_people": {"description": "Description for /people command", "variables": common_vars},
        "usage_search": {"description": "Usage example for /search (e.g. '/search sunset')", "variables": common_vars},
        "usage_find": {"description": "Usage example for /find", "variables": common_vars},
        "usage_person": {"description": "Usage example for /person", "variables": common_vars},
        "usage_place": {"description": "Usage example for /place", "variables": common_vars},
        "usage_latest": {"description": "Usage example for /latest", "variables": common_vars},
        "usage_random": {"description": "Usage example for /random", "variables": common_vars},
        "usage_favorites": {"description": "Usage example for /favorites", "variables": common_vars},
        "usage_events": {"description": "Usage example for /events", "variables": common_vars},
        "usage_memory": {"description": "Usage example for /memory", "variables": common_vars},
    }

    # --- Gitea-specific ---
    repo_fields = {
        "full_name": "Repository full name (owner/repo)",
        "description": "Repository description",
    }
    issue_fields = {
        "repo": "Repository name",
        "number": "Issue number",
        "title": "Issue title",
        "url": "Issue URL",
        "user": "Issue author",
    }
    pr_fields = {
        "repo": "Repository name",
        "number": "PR number",
        "title": "PR title",
        "url": "PR URL",
        "user": "PR author",
    }
    commit_fields = {
        "repo": "Repository name",
        "short_id": "Short commit hash",
        "message": "Commit message",
        "author": "Commit author",
    }
    gitea = {
        "status": {
            "description": "/status Gitea server summary",
            "variables": {**common_vars, "repos_count": "Number of tracked repositories", "server_version": "Gitea server version", "last_event": "Last event timestamp"},
        },
        "repos": {
            "description": "/repos tracked repositories",
            "variables": {**common_vars, "repos": "List of repo dicts (use {% for repo in repos %})"},
            "repo_fields": repo_fields,
        },
        "issues": {
            "description": "/issues open issues",
            "variables": {**common_vars, "issues": "List of issue dicts (use {% for issue in issues %})"},
            "issue_fields": issue_fields,
        },
        "prs": {
            "description": "/prs open pull requests",
            "variables": {**common_vars, "prs": "List of PR dicts (use {% for pr in prs %})"},
            "pr_fields": pr_fields,
        },
        "commits": {
            "description": "/commits recent commits",
            "variables": {**common_vars, "commits": "List of commit dicts (use {% for c in commits %})"},
            "commit_fields": commit_fields,
        },
        "desc_repos": {"description": "Description for /repos command", "variables": common_vars},
        "desc_issues": {"description": "Description for /issues command", "variables": common_vars},
        "desc_prs": {"description": "Description for /prs command", "variables": common_vars},
        "desc_commits": {"description": "Description for /commits command", "variables": common_vars},
    }

    # --- Planka-specific ---
    board_fields = {"name": "Board name"}
    card_fields_planka = {
        "name": "Card name",
        "list_name": "List the card belongs to",
        "board_name": "Board the card belongs to",
    }
    list_fields = {"name": "List name", "board_name": "Board name"}
    planka = {
        "status": {
            "description": "/status Planka board summary",
            "variables": {**common_vars, "boards_count": "Number of tracked boards", "last_event": "Last event timestamp"},
        },
        "boards": {
            "description": "/boards tracked boards",
            "variables": {**common_vars, "boards": "List of board dicts (use {% for board in boards %})"},
            "board_fields": board_fields,
        },
        "cards": {
            "description": "/cards recent cards",
            "variables": {**common_vars, "cards": "List of card dicts (use {% for card in cards %})"},
            "card_fields": card_fields_planka,
        },
        "lists": {
            "description": "/lists board lists",
            "variables": {**common_vars, "lists": "List of list dicts (use {% for lst in lists %})"},
            "list_fields": list_fields,
        },
        "desc_boards": {"description": "Description for /boards command", "variables": common_vars},
        "desc_cards": {"description": "Description for /cards command", "variables": common_vars},
        "desc_lists": {"description": "Description for /lists command", "variables": common_vars},
    }

    # --- NUT-specific ---
    device_fields = {
        "name": "UPS device name",
        "description": "UPS description",
        "model": "UPS model",
        "battery_charge": "Battery charge percentage",
        "battery_runtime": "Estimated runtime (formatted)",
        "input_voltage": "Input voltage",
        "output_voltage": "Output voltage",
    }
    nut = {
        "status": {
            "description": "/status UPS summary",
            "variables": {**common_vars, "devices_count": "Number of monitored devices", "last_event": "Last event timestamp"},
        },
        "devices": {
            "description": "/devices monitored UPS devices",
            "variables": {**common_vars, "devices": "List of device dicts (use {% for d in devices %})"},
            "device_fields": device_fields,
        },
        "battery": {
            "description": "/battery battery report",
            "variables": {**common_vars, "devices": "List of UPS dicts (use {% for ups in devices %})"},
            "device_fields": device_fields,
        },
        "desc_devices": {"description": "Description for /devices command", "variables": common_vars},
        "desc_battery": {"description": "Description for /battery command", "variables": common_vars},
    }

    # --- Google Photos-specific ---
    gp_asset_fields = {
        "id": "Asset ID",
        "filename": "Original filename",
        "type": "IMAGE or VIDEO",
        "created_at": "Creation date/time (ISO 8601)",
    }
    google_photos = {
        "status": {
            "description": "/status Google Photos summary",
            "variables": {**common_vars, "trackers_active": "Number of active trackers", "trackers_total": "Total tracker count", "total_albums": "Total tracked albums", "last_event": "Last event timestamp"},
        },
        "albums": {
            "description": "/albums tracked albums",
            "variables": {**common_vars, "albums": "List of album dicts (use {% for album in albums %})"},
            "album_fields": album_fields,
        },
        "latest": {
            "description": "/latest recent photos",
            "variables": {**common_vars, "assets": "List of asset dicts (use {% for asset in assets %})", "count": "Number of results"},
            "asset_fields": gp_asset_fields,
        },
        "search": {
            "description": "/search photo search results",
            "variables": {**common_vars, "assets": "List of asset dicts (use {% for asset in assets %})", "query": "Search query", "count": "Number of results"},
            "asset_fields": gp_asset_fields,
        },
        "random": {
            "description": "/random random photos",
            "variables": {**common_vars, "assets": "List of asset dicts (use {% for asset in assets %})", "count": "Number of results"},
            "asset_fields": gp_asset_fields,
        },
        "desc_albums": {"description": "Description for /albums command", "variables": common_vars},
        "desc_latest": {"description": "Description for /latest command", "variables": common_vars},
        "desc_search": {"description": "Description for /search command", "variables": common_vars},
        "desc_random": {"description": "Description for /random command", "variables": common_vars},
        "usage_latest": {"description": "Usage example for /latest", "variables": common_vars},
        "usage_search": {"description": "Usage example for /search", "variables": common_vars},
        "usage_random": {"description": "Usage example for /random", "variables": common_vars},
    }

    # --- Webhook-specific ---
    webhook = {
        "status": {
            "description": "/status webhook provider summary",
            "variables": {
                **common_vars,
                "trackers_active": "Number of enabled trackers attached to the webhook provider",
                "trackers_total": "Total number of trackers attached to the webhook provider",
                "provider_name": "Webhook provider name",
                "last_event": "Last event timestamp ('YYYY-MM-DD HH:MM' or '-')",
            },
        },
    }

    # --- Bridge self-monitoring ---
    bridge_self_poll_failure_fields = {
        "tracker_id": "Tracker id (int)",
        "tracker_name": "Tracker display name",
        "count": "Consecutive poll failures",
    }
    bridge_self_target_failure_fields = {
        "target_id": "Target id (int)",
        "target_name": "Target display name",
        "count": "Consecutive send failures",
    }
    bridge_self = {
        "status": {
            "description": "/status snapshot of all bridge_self counters",
            "variables": {
                **common_vars,
                "poll_failures": "List of {tracker_id, tracker_name, count} dicts (use {% for f in poll_failures %})",
                "deferred_pending": "Pending deferred-dispatch row count for this user",
                "deferred_threshold": "Deferred backlog threshold from provider config",
                "target_failures": "List of {target_id, target_name, count} dicts (use {% for f in target_failures %})",
            },
            "poll_failure_fields": bridge_self_poll_failure_fields,
            "target_failure_fields": bridge_self_target_failure_fields,
        },
        "thresholds": {
            "description": "/thresholds configured alert thresholds",
            "variables": {
                **common_vars,
                "poll_failure_threshold": "Tracker poll failure threshold (int)",
                "deferred_backlog_threshold": "Deferred backlog threshold (int)",
                "target_failure_threshold": "Target send failure threshold (int)",
            },
        },
        "reset": {
            "description": "/reset result of a manual counter reset",
            "variables": {
                **common_vars,
                "subject_type": "'tracker', 'target', or 'all' (empty on parse error)",
                "subject_id": "Subject id (int) or None for 'all' / errors",
                "subject_name": "Display name of the subject (empty on error)",
                "previous_count": "Counter value before reset",
                "success": "Whether the reset succeeded (boolean)",
                "error_message": "Error message when success=False (None on success)",
            },
        },
        "health": {
            "description": "/health terse one-line summary",
            "variables": {
                **common_vars,
                "healthy": "Whether everything is at zero (boolean)",
                "summary": "Human-readable one-line summary",
                "tracker_count": "Total enabled tracker count for this user",
                "failing_tracker_count": "Number of trackers with non-zero poll failures",
                "deferred_pending": "Pending deferred-dispatch row count for this user",
                "failing_target_count": "Number of targets with non-zero send failures",
            },
        },
        "desc_thresholds": {"description": "Description for /thresholds command", "variables": common_vars},
        "desc_reset": {"description": "Description for /reset command", "variables": common_vars},
        "desc_health": {"description": "Description for /health command", "variables": common_vars},
        "usage_reset": {"description": "Usage example for /reset", "variables": common_vars},
    }

    return {
        **shared,
        "immich": immich,
        "gitea": gitea,
        "planka": planka,
        "nut": nut,
        "google_photos": google_photos,
        "webhook": webhook,
        "bridge_self": bridge_self,
    }


@router.get("")
async def list_configs(
    provider_type: str | None = None,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    from sqlalchemy import or_
    query = select(CommandTemplateConfig).where(
        or_(CommandTemplateConfig.user_id == user.id, CommandTemplateConfig.user_id == 0)
    )
    if provider_type:
        query = query.where(CommandTemplateConfig.provider_type == provider_type)
    result = await session.exec(query)
    return [await _response(session, c) for c in result.all()]


@router.post("", status_code=status.HTTP_201_CREATED)
async def create_config(
    body: CommandTemplateConfigCreate,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    config = CommandTemplateConfig(
        user_id=user.id,
        provider_type=body.provider_type,
        name=body.name,
        description=body.description or "",
        icon=body.icon or "",
    )
    session.add(config)
    await session.flush()
    if body.slots:
        await _save_slots(session, config.id, body.slots)
    await session.commit()
    await session.refresh(config)
    return await _response(session, config)


@router.get("/{config_id}")
async def get_config(
    config_id: int,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    config = await _get(session, config_id, user.id)
    return await _response(session, config)


@router.put("/{config_id}")
async def update_config(
    config_id: int,
    body: CommandTemplateConfigUpdate,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    config = await _get(session, config_id, user.id)
    if config.user_id == 0 and user.role != "admin":
        raise HTTPException(status_code=403, detail="Cannot modify system default configs")
    for field, value in body.model_dump(exclude_unset=True, exclude={"slots"}).items():
        if value is not None:
            setattr(config, field, value)
    session.add(config)
    if body.slots is not None:
        await _save_slots(session, config.id, body.slots)
    await session.commit()
    await session.refresh(config)
    return await _response(session, config)


@router.delete("/{config_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_config(
    config_id: int,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    from .delete_protection import check_command_template_config, raise_if_used
    config = await _get(session, config_id, user.id)
    if config.user_id == 0 and user.role != "admin":
        raise HTTPException(status_code=403, detail="Cannot delete system default configs")
    raise_if_used(await check_command_template_config(session, config.id), config.name)
    # Bulk delete slot rows so the round-trip count stays O(1) regardless
    # of how many locale/slot combinations the config carries.
    from sqlalchemy import delete as sa_delete
    await session.execute(
        sa_delete(CommandTemplateSlot).where(
            CommandTemplateSlot.config_id == config.id
        )
    )
    await session.delete(config)
    await session.commit()


class PreviewRequest(BaseModel):
    template: str


@router.post("/preview-raw")
async def preview_raw(
    body: PreviewRequest,
    user: User = Depends(get_current_user),
):
    """Render arbitrary Jinja2 template text with sample command context."""
    sample_ctx = {
        # /start
        "bot_name": "NotifyBridgeBot",
        "locale": "en",
        # /status
        "trackers_active": 2,
        "trackers_total": 3,
        "total_albums": 5,
        "last_event": "2026-03-19 14:30",
        # /help
        "commands": [
            {"name": "status", "description": "Show tracker status", "usage": ""},
            {"name": "albums", "description": "List tracked albums", "usage": ""},
            {"name": "latest", "description": "Show latest photos", "usage": "/latest 10"},
            {"name": "search", "description": "Smart search (AI)", "usage": "/search sunset at the beach"},
        ],
        # /albums, /summary — provide photo/video split, sharing, owner so the
        # enriched summary template previews fully.
        "albums": [
            {"name": "Family Photos", "asset_count": 142, "photo_count": 120, "video_count": 22, "shared": True, "owner": "Alice", "id": "abc-123", "public_url": "https://immich.example.com/share/abc123"},
            {"name": "Vacation 2025", "asset_count": 87, "photo_count": 80, "video_count": 7, "shared": False, "owner": "Bob", "id": "def-456", "public_url": ""},
        ],
        # /events
        "events": [
            {"type": "assets_added", "album": "Family Photos", "count": 3, "date": "03/19 14:30"},
            {"type": "assets_removed", "album": "Vacation 2025", "count": 1, "date": "03/19 12:00"},
        ],
        # /people
        "people": ["Alice", "Bob", "Charlie"],
        # /search, /find, /person, /place, /latest, /favorites, /random, /memory
        # ``filename`` is the canonical key (matches notification context and
        # build_asset_dict output); ``originalFileName`` is kept as an alias
        # so templates still using the old key render in preview.
        "assets": [
            {"id": "a1", "filename": "IMG_001.jpg", "originalFileName": "IMG_001.jpg", "type": "IMAGE", "created_at": "2026-03-19T14:30:00", "createdAt": "2026-03-19T14:30:00", "year": 2024, "public_url": "https://immich.example.com/share/abc123/photos/a1", "city": "Paris", "country": "France", "is_favorite": True},
            {"id": "a2", "filename": "VID_002.mp4", "originalFileName": "VID_002.mp4", "type": "VIDEO", "created_at": "2026-03-19T15:00:00", "createdAt": "2026-03-19T15:00:00", "year": 2023, "public_url": "", "city": "", "country": "", "is_favorite": False},
        ],
        "query": "sunset",
        "command": "search",
        "count": 2,
        # /rate_limited
        "wait": 15,
        # --- Home Assistant: /status, /entities, /state, /areas ---
        "ok": True,
        "message": "OK",
        "provider_name": "Home Assistant",
        "url": "http://homeassistant.local:8123",
        "entity_count": 142,
        "area_count": 8,
        "entities": [
            {
                "entity_id": "binary_sensor.front_door",
                "friendly_name": "Front Door",
                "domain": "binary_sensor",
                "state": "off",
                "attributes": {"device_class": "door", "friendly_name": "Front Door"},
                "device_class": "door",
                "unit_of_measurement": None,
                "last_changed": "2026-05-13T12:34:56.789+00:00",
                "last_updated": "2026-05-13T12:34:56.789+00:00",
            },
            {
                "entity_id": "sensor.kitchen_temperature",
                "friendly_name": "Kitchen Temperature",
                "domain": "sensor",
                "state": "21.4",
                "attributes": {"unit_of_measurement": "°C", "friendly_name": "Kitchen Temperature"},
                "device_class": "temperature",
                "unit_of_measurement": "°C",
                "last_changed": "2026-05-13T12:30:00+00:00",
                "last_updated": "2026-05-13T12:30:00+00:00",
            },
        ],
        "glob": "binary_sensor.*",
        "total": 12,
        "shown": 2,
        # /state — single entity drill-down. ``found`` controls which branch
        # of the template renders.
        "found": True,
        "entity_id": "light.kitchen",
        "friendly_name": "Kitchen Light",
        "domain": "light",
        "state": "on",
        "attributes": {
            "brightness": 200,
            "color_mode": "brightness",
        },
        "hidden_attr_count": 0,
        "device_class": None,
        "unit_of_measurement": None,
        "last_changed": "2026-05-13T12:34:56.789+00:00",
        "last_updated": "2026-05-13T12:34:56.789+00:00",
        "reason": "",
        "error": "",
        # /areas
        "areas": [
            {"area_id": "kitchen", "name": "Kitchen", "entity_count": 14},
            {"area_id": "entrance", "name": "Entrance", "entity_count": 4},
        ],
        # --- Bridge self-monitoring ---
        # /status — three categories of failure (preview shows non-empty data
        # so operators can see how the template renders failures, not the
        # all-zero case)
        "poll_failures": [
            {"tracker_id": 12, "tracker_name": "Family Photos poller", "count": 3},
            {"tracker_id": 18, "tracker_name": "Vacation 2025 poller", "count": 5},
        ],
        "deferred_pending": 47,
        "deferred_threshold": 100,
        "target_failures": [
            {"target_id": 4, "target_name": "Telegram - Family chat", "count": 7},
        ],
        # /thresholds — user's configured thresholds
        "poll_failure_threshold": 3,
        "deferred_backlog_threshold": 100,
        "target_failure_threshold": 5,
        # /reset — sample success result
        "subject_type": "tracker",
        "subject_id": 12,
        "subject_name": "Family Photos poller",
        "previous_count": 3,
        "success": True,
        "error_message": None,
        # /health — sample "unhealthy" line that matches the failure data
        # above. Templates that only branch on ``healthy`` still preview
        # cleanly — operators wanting the healthy case can flip the flag
        # in their template editor.
        "healthy": False,
        "summary": "2 trackers failing, 47 deferred, 1 target failing",
        "tracker_count": 3,
        "failing_tracker_count": 2,
        "failing_target_count": 1,
    }

    return render_template_preview(body.template, sample_ctx)
