"""Template acquisition and generic-template generation for MCP document tools."""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, Optional

from tokenmoulds.mcp.cache import TemplateFormat
from tokenmoulds.mcp.tools.token_utils import extract_token_payload

if TYPE_CHECKING:
    from tokenmoulds.mcp.server import TokenMouldsServer


GENERIC_BRAND_NAME = "_tokenmoulds_generic_"

GENERIC_RECIPE_INPUTS = {
    "primary_color": "#2563EB",  # Professional blue
    "secondary_color": "#DC2626",  # Accent red
    "font_sans": "Arial",  # Universal availability
    "font_serif": "Georgia",  # Classic serif
    "baseline_pt": 11.0,
    "type_scale_ratio": 1.25,  # Major third
    "brand_tone": 0.5,  # Balanced
    "content_density": 0.4,  # Comfortable reading
    "contrast_ratio": 4.5,  # WCAG AA
    "locale": "US",
    "paper_size": "letter",
    "document_type": "report",
}


async def _ensure_generic_template(
    server: "TokenMouldsServer",
    format: TemplateFormat,
) -> Optional[bytes]:
    """Ensure generic TokenMoulds template exists, creating if needed.

    Returns cached generic template or generates a new one.
    This is the fallback when no brand is specified.
    """
    cache = server.cache_manager

    # Check if generic template is cached
    cached = cache.get_template(GENERIC_BRAND_NAME, format)
    if cached:
        return cached

    # Generate generic template using recipe builder
    try:
        from tokenmoulds.dtcg.emitter import emit_tokens_to_dict
        from tokenmoulds.dtcg.recipe import RecipeInputs, build_recipe

        # Build recipe from generic inputs
        inputs = RecipeInputs(**GENERIC_RECIPE_INPUTS)
        recipe = build_recipe(inputs)
        tokens = emit_tokens_to_dict(recipe)

        # Store tokens
        server.loaded_tokens[GENERIC_BRAND_NAME] = tokens
        cache.save_tokens(GENERIC_BRAND_NAME, tokens)

        # Generate template using appropriate emitter
        template_bytes = await _generate_template_for_format(
            tokens, format, server.fonts_dir
        )

        if template_bytes:
            # Cache the template
            token_hash = cache.compute_token_hash(tokens)
            cache.set_template(
                GENERIC_BRAND_NAME,
                format,
                template_bytes,
                token_hash,
                fonts_embedded=[],  # Generic uses system fonts
                styles_count=276,
                validation_status="generated",
                iso_compliant=True,
                wcag_level="AA",
            )

        return template_bytes

    except Exception:
        # Log but don't fail - return None
        return None


async def _generate_template_for_format(
    tokens: Dict[str, Any],
    format: TemplateFormat,
    fonts_dir: Optional[Path] = None,
) -> Optional[bytes]:
    """Generate template bytes for a specific format."""
    try:
        from tokenmoulds.ir import build_document_ir

        # Build IR
        token_payload = extract_token_payload(tokens)
        document_ir = build_document_ir(token_payload, "generic", locale="US")

        if format == TemplateFormat.WORD:
            from tokenmoulds.emitters import WordDocumentEmitter
            from tokenmoulds.styles import create_style_resolver_from_tokens

            style_resolver = create_style_resolver_from_tokens(
                token_payload,
                body_color=document_ir.body_style.color,
                heading_color=(
                    document_ir.heading_styles[0].color
                    if document_ir.heading_styles
                    else document_ir.body_style.color
                ),
            )
            emitter = WordDocumentEmitter(
                document_ir,
                template_root=None,
                embed_fonts=False,
                style_resolver=style_resolver,
            )
            return emitter.build_package()

        elif format == TemplateFormat.POWERPOINT:
            from tokenmoulds.emitters import PowerPointEmitter

            emitter = PowerPointEmitter(document_ir, fonts_dir=fonts_dir)
            return emitter.build_package()

        elif format == TemplateFormat.THEME:
            from tokenmoulds.themes.thmx import ThemeDefinition, ThmxEmitter

            theme = ThemeDefinition.from_color_theme(
                color_theme=document_ir.color_theme,
                typography=document_ir.typography,
            )
            emitter = ThmxEmitter(theme)
            return emitter.emit()

        # Add other formats as they become available

    except Exception:
        pass

    return None


async def _get_word_template(
    server: "TokenMouldsServer",
    brand_name: Optional[str],
) -> tuple[Optional[bytes], str]:
    """Get Word template, generating on-demand if needed."""
    cache = server.cache_manager

    # Try brand-specific first
    if brand_name and brand_name in server.loaded_tokens:
        tokens = server.loaded_tokens[brand_name]
        token_hash = cache.compute_token_hash(tokens)

        # Check cache
        cached = cache.get_template(brand_name, TemplateFormat.WORD, token_hash)
        if cached:
            return cached, f"brand:{brand_name}"

        # Generate on-demand if tokens exist but template doesn't
        generated = await _generate_template_for_format(
            tokens, TemplateFormat.WORD, server.fonts_dir
        )
        if generated:
            cache.set_template(brand_name, TemplateFormat.WORD, generated, token_hash)
            return generated, f"brand:{brand_name}:generated"

    # Try generic fallback
    generic = await _ensure_generic_template(server, TemplateFormat.WORD)
    if generic:
        return generic, "generic:tokenmoulds"

    return None, "none"


async def _get_powerpoint_template(
    server: "TokenMouldsServer",
    brand_name: Optional[str],
) -> tuple[Optional[bytes], str]:
    """Get PowerPoint template."""
    cache = server.cache_manager

    if brand_name and brand_name in server.loaded_tokens:
        tokens = server.loaded_tokens[brand_name]
        token_hash = cache.compute_token_hash(tokens)
        cached = cache.get_template(brand_name, TemplateFormat.POWERPOINT, token_hash)
        if cached:
            return cached, f"brand:{brand_name}"

    generic = await _ensure_generic_template(server, TemplateFormat.POWERPOINT)
    if generic:
        return generic, "generic:tokenmoulds"

    return None, "none"


async def _get_excel_template(
    server: "TokenMouldsServer",
    brand_name: Optional[str],
) -> tuple[Optional[bytes], str]:
    """Get Excel template."""
    cache = server.cache_manager

    if brand_name and brand_name in server.loaded_tokens:
        tokens = server.loaded_tokens[brand_name]
        token_hash = cache.compute_token_hash(tokens)
        cached = cache.get_template(brand_name, TemplateFormat.EXCEL, token_hash)
        if cached:
            return cached, f"brand:{brand_name}"

    generic = await _ensure_generic_template(server, TemplateFormat.EXCEL)
    if generic:
        return generic, "generic:tokenmoulds"

    return None, "none"


async def _get_writer_template(
    server: "TokenMouldsServer",
    brand_name: Optional[str],
) -> tuple[Optional[bytes], str]:
    """Get Writer template."""
    cache = server.cache_manager

    if brand_name and brand_name in server.loaded_tokens:
        tokens = server.loaded_tokens[brand_name]
        token_hash = cache.compute_token_hash(tokens)
        cached = cache.get_template(brand_name, TemplateFormat.WRITER, token_hash)
        if cached:
            return cached, f"brand:{brand_name}"

    generic = await _ensure_generic_template(server, TemplateFormat.WRITER)
    if generic:
        return generic, "generic:tokenmoulds"

    return None, "none"


async def _get_impress_template(
    server: "TokenMouldsServer",
    brand_name: Optional[str],
) -> tuple[Optional[bytes], str]:
    """Get Impress template."""
    cache = server.cache_manager

    if brand_name and brand_name in server.loaded_tokens:
        tokens = server.loaded_tokens[brand_name]
        token_hash = cache.compute_token_hash(tokens)
        cached = cache.get_template(brand_name, TemplateFormat.IMPRESS, token_hash)
        if cached:
            return cached, f"brand:{brand_name}"

    generic = await _ensure_generic_template(server, TemplateFormat.IMPRESS)
    if generic:
        return generic, "generic:tokenmoulds"

    return None, "none"


def _get_style_context(
    server: "TokenMouldsServer",
    brand_name: Optional[str],
) -> Dict[str, Any]:
    """Extract style context from tokens for content injection."""
    tokens = None
    if brand_name and brand_name in server.loaded_tokens:
        tokens = server.loaded_tokens[brand_name]
    elif GENERIC_BRAND_NAME in server.loaded_tokens:
        tokens = server.loaded_tokens[GENERIC_BRAND_NAME]

    if tokens is None:
        return {"table_style": "LightGrid-Accent1"}

    # Try to extract table style from tokens
    styles = tokens.get("styles", {})
    table = styles.get("table", {})
    base = table.get("base", {})
    table_style = base.get("style_id", "LightGrid-Accent1")

    return {"table_style": table_style}
