"""
Template integration utilities for FastAPI application.

This module provides utilities for template rendering with common context
and helper functions.

Series Identifier Convention:
    - `key`: Primary identifier for all series operations
      (URL-safe, e.g., "attack-on-titan")
    - `folder`: Metadata only for filesystem operations and display
      (e.g., "Attack on Titan (2013)")

All template helpers that handle series data use `key` for identification and
provide `folder` as display metadata only.
"""
import logging
import time
from pathlib import Path
from typing import Any, Dict, List, Optional

from fastapi import Request
from fastapi.templating import Jinja2Templates

logger = logging.getLogger(__name__)

# Configure templates directory
TEMPLATES_DIR = Path(__file__).parent.parent / "web" / "templates"
templates = Jinja2Templates(directory=str(TEMPLATES_DIR))

# Version token for static asset cache-busting; changes on every server start.
STATIC_VERSION: str = str(int(time.time()))


def get_base_context(
    request: Request, title: str = "Aniworld"
) -> Dict[str, Any]:
    """
    Get base context for all templates.
    
    Args:
        request: FastAPI request object
        title: Page title
        
    Returns:
        Dictionary with base context variables
    """
    return {
        "request": request,
        "title": title,
        "app_name": "Aniworld Download Manager",
        "version": "1.0.1",
        "static_v": STATIC_VERSION,
    }


def render_template(
    template_name: str,
    request: Request,
    context: Optional[Dict[str, Any]] = None,
    title: Optional[str] = None
):
    """
    Render a template with base context.
    
    Args:
        template_name: Name of the template file
        request: FastAPI request object
        context: Additional context variables
        title: Page title (optional)
        
    Returns:
        TemplateResponse object
    """
    base_context = get_base_context(
        request,
        title or template_name.replace('.html', '').replace('_', ' ').title()
    )
    
    if context:
        base_context.update(context)
    
    return templates.TemplateResponse(template_name, base_context)


def validate_template_exists(template_name: str) -> bool:
    """
    Check if a template file exists.
    
    Args:
        template_name: Name of the template file
        
    Returns:
        True if template exists, False otherwise
    """
    template_path = TEMPLATES_DIR / template_name
    return template_path.exists()


def list_available_templates() -> list[str]:
    """
    Get list of all available template files.

    Returns:
        List of template file names
    """
    if not TEMPLATES_DIR.exists():
        return []

    return [
        f.name
        for f in TEMPLATES_DIR.glob("*.html")
        if f.is_file()
    ]


def prepare_series_context(
    series_data: List[Dict[str, Any]],
    sort_by: str = "name"
) -> List[Dict[str, Any]]:
    """
    Prepare series data for template rendering.

    This function ensures series data follows the identifier convention:
    - `key` is used as the primary identifier for all operations
    - `folder` is included as metadata for display purposes

    Args:
        series_data: List of series dictionaries from the API
        sort_by: Field to sort by ("name", "key", or "folder")

    Returns:
        List of series dictionaries prepared for template use

    Raises:
        ValueError: If series_data contains items without required 'key' field

    Example:
        >>> series = [
        ...     {"key": "attack-on-titan", "name": "Attack on Titan",
        ...      "folder": "Attack on Titan (2013)"},
        ...     {"key": "one-piece", "name": "One Piece",
        ...      "folder": "One Piece (1999)"}
        ... ]
        >>> prepared = prepare_series_context(series, sort_by="name")
    """
    if not series_data:
        return []

    prepared = []
    for series in series_data:
        if "key" not in series:
            logger.warning(
                "Series data missing 'key' field: %s",
                series.get("name", "unknown")
            )
            continue

        prepared_item = {
            "key": series["key"],
            "name": series.get("name", series["key"]),
            "folder": series.get("folder", ""),
            **{k: v for k, v in series.items()
               if k not in ("key", "name", "folder")}
        }
        prepared.append(prepared_item)

    # Sort by specified field
    if sort_by in ("name", "key", "folder"):
        prepared.sort(key=lambda x: x.get(sort_by, "").lower())

    return prepared


def get_series_by_key(
    series_data: List[Dict[str, Any]],
    key: str
) -> Optional[Dict[str, Any]]:
    """
    Find a series in the data by its key.

    Uses `key` as the identifier (not `folder`) following the project
    identifier convention.

    Args:
        series_data: List of series dictionaries
        key: The unique series key to search for

    Returns:
        The series dictionary if found, None otherwise

    Example:
        >>> series = [{"key": "attack-on-titan", "name": "Attack on Titan"}]
        >>> result = get_series_by_key(series, "attack-on-titan")
        >>> result["name"]
        'Attack on Titan'
    """
    for series in series_data:
        if series.get("key") == key:
            return series
    return None


def filter_series_by_missing_episodes(
    series_data: List[Dict[str, Any]]
) -> List[Dict[str, Any]]:
    """
    Filter series to only include those with missing episodes.

    Args:
        series_data: List of series dictionaries with 'missing_episodes' field

    Returns:
        Filtered list containing only series with missing episodes

    Note:
        Identification uses `key`, not `folder`.
    """
    return [
        series for series in series_data
        if series.get("missing_episodes")
        and any(episodes for episodes in series["missing_episodes"].values())
    ]
