"""Brand configuration MCP tools for TokenMoulds."""

from __future__ import annotations

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

if TYPE_CHECKING:
    from tokenmoulds.mcp.server import TokenMouldsServer


# JSON Schema for configure_brand tool
BRAND_TOOL_SCHEMA: Dict[str, Any] = {
    "type": "object",
    "properties": {
        "action": {
            "type": "string",
            "enum": ["load_directory", "extract_from_url", "list_brands", "set_active"],
            "description": "Configuration action to perform",
        },
        "path": {
            "type": "string",
            "description": "Token directory path (for load_directory action)",
        },
        "url": {
            "type": "string",
            "description": "Website URL to extract brand from (for extract_from_url action)",
        },
        "brand_name": {
            "type": "string",
            "description": "Brand identifier (for set_active action or naming loaded brand)",
        },
    },
    "required": ["action"],
}


# JSON Schema for list_styles tool
STYLES_TOOL_SCHEMA: Dict[str, Any] = {
    "type": "object",
    "properties": {
        "document_type": {
            "type": "string",
            "enum": ["word", "powerpoint", "excel"],
            "description": "Document type to list styles for",
        },
        "category": {
            "type": "string",
            "enum": ["all", "headings", "body", "lists", "tables"],
            "description": "Style category filter (optional, defaults to 'all')",
        },
    },
    "required": ["document_type"],
}


async def configure_brand(
    arguments: Dict[str, Any],
    server: "TokenMouldsServer",
) -> Dict[str, Any]:
    """Configure brand/tokens for document generation.

    Args:
        arguments: Tool arguments from MCP call
        server: TokenMouldsServer instance for state management

    Returns:
        Result dictionary with configuration status
    """
    action = arguments.get("action")

    if action == "load_directory":
        return await _load_directory(arguments, server)
    elif action == "extract_from_url":
        return await _extract_from_url(arguments, server)
    elif action == "list_brands":
        return _list_brands(server)
    elif action == "set_active":
        return _set_active_brand(arguments, server)
    else:
        return {"error": f"Unknown action: {action}"}


async def _load_directory(
    arguments: Dict[str, Any],
    server: "TokenMouldsServer",
) -> Dict[str, Any]:
    """Load tokens from a directory."""
    path_str = arguments.get("path")
    if not path_str:
        return {"error": "Missing 'path' parameter for load_directory action"}

    path = Path(path_str)
    if not path.exists():
        return {"error": f"Directory not found: {path}"}

    brand_name = arguments.get("brand_name", path.name)

    try:
        server._load_tokens_from_directory(path, brand_name)

        if brand_name not in server.loaded_tokens:
            return {
                "error": f"No token files found in {path}",
                "suggestion": "Directory should contain *.tokens.json (DTCG) or *-design-tokens.json files",
            }

        server.active_brand = brand_name

        return {
            "success": True,
            "action": "load_directory",
            "brand_name": brand_name,
            "path": str(path),
            "active_brand": server.active_brand,
            "loaded_brands": list(server.loaded_tokens.keys()),
        }

    except Exception as e:
        return {"error": f"Failed to load tokens: {str(e)}"}


async def _extract_from_url(
    arguments: Dict[str, Any],
    server: "TokenMouldsServer",
) -> Dict[str, Any]:
    """Extract brand from a website URL."""
    url = arguments.get("url")
    if not url:
        return {"error": "Missing 'url' parameter for extract_from_url action"}

    brand_name = arguments.get("brand_name", "extracted")

    try:
        # Import brand extraction module
        from tokenmoulds.brand_from_url import extract_brand

        # Extract brand colors and fonts (blocking I/O, run in executor)
        loop = asyncio.get_running_loop()
        brand_data = await loop.run_in_executor(None, extract_brand, url)

        # Convert to tokens format
        from tokenmoulds.dtcg import build_recipe, RecipeInputs

        recipe_inputs = RecipeInputs(
            primary_color=brand_data.primary_color,
            secondary_color=brand_data.secondary_color,
            font_sans=brand_data.body_font,
            font_serif=brand_data.heading_font,
        )

        from tokenmoulds.dtcg import emit_tokens_to_dict

        dtcg_file = build_recipe(recipe_inputs)
        tokens = emit_tokens_to_dict(dtcg_file)

        server.loaded_tokens[brand_name] = tokens
        server.active_brand = brand_name

        return {
            "success": True,
            "action": "extract_from_url",
            "url": url,
            "brand_name": brand_name,
            "extracted": {
                "primary_color": brand_data.primary_color,
                "secondary_color": brand_data.secondary_color,
                "font_sans": brand_data.body_font,
                "font_serif": brand_data.heading_font,
            },
            "active_brand": server.active_brand,
        }

    except ImportError:
        return {
            "error": "Brand extraction module not available",
            "suggestion": "Use load_directory action with existing tokens instead",
        }
    except Exception as e:
        return {"error": f"Failed to extract brand from URL: {str(e)}"}


def _list_brands(server: "TokenMouldsServer") -> Dict[str, Any]:
    """List loaded brands."""
    return {
        "success": True,
        "action": "list_brands",
        "active_brand": server.active_brand,
        "loaded_brands": list(server.loaded_tokens.keys()),
        "brands_count": len(server.loaded_tokens),
    }


def _set_active_brand(
    arguments: Dict[str, Any],
    server: "TokenMouldsServer",
) -> Dict[str, Any]:
    """Set the active brand."""
    brand_name = arguments.get("brand_name")
    if not brand_name:
        return {"error": "Missing 'brand_name' parameter for set_active action"}

    if brand_name not in server.loaded_tokens:
        return {
            "error": f"Brand '{brand_name}' not loaded",
            "available_brands": list(server.loaded_tokens.keys()),
            "suggestion": "Use list_brands action to see available brands, or load_directory to load new tokens",
        }

    server.active_brand = brand_name

    return {
        "success": True,
        "action": "set_active",
        "active_brand": server.active_brand,
        "loaded_brands": list(server.loaded_tokens.keys()),
    }


async def list_styles(
    arguments: Dict[str, Any],
    tokens: Optional[Dict[str, Any]],
) -> Dict[str, Any]:
    """List available document styles.

    Args:
        arguments: Tool arguments from MCP call
        tokens: Loaded design tokens

    Returns:
        Result dictionary with available styles
    """
    document_type = arguments.get("document_type", "word")
    category = arguments.get("category", "all")

    # Define available styles per document type
    style_getters = {
        "word": _get_word_styles,
        "powerpoint": _get_powerpoint_styles,
        "excel": _get_excel_styles,
    }

    getter = style_getters.get(document_type, _get_word_styles)
    styles = getter(category)

    # Extract brand colors if tokens loaded
    brand_colors = {}
    if tokens:
        brand_colors = _extract_brand_colors(tokens)

    return {
        "success": True,
        "document_type": document_type,
        "category": category,
        "styles": styles,
        "styles_count": len(styles),
        "brand_colors": brand_colors,
        "message": f"All {len(styles)} styles are themed from your tokens - zero Office defaults.",
    }


def _get_word_styles(category: str) -> List[Dict[str, str]]:
    """Get Word style definitions."""
    all_styles = [
        # Headings
        {
            "name": "Heading 1",
            "type": "heading",
            "description": "Primary section heading",
        },
        {"name": "Heading 2", "type": "heading", "description": "Secondary heading"},
        {"name": "Heading 3", "type": "heading", "description": "Tertiary heading"},
        {"name": "Heading 4", "type": "heading", "description": "Fourth-level heading"},
        {"name": "Heading 5", "type": "heading", "description": "Fifth-level heading"},
        {"name": "Heading 6", "type": "heading", "description": "Sixth-level heading"},
        {"name": "Title", "type": "heading", "description": "Document title"},
        {"name": "Subtitle", "type": "heading", "description": "Document subtitle"},
        # Body
        {"name": "Normal", "type": "body", "description": "Standard body text"},
        {"name": "Body Text", "type": "body", "description": "Body paragraph text"},
        {"name": "Body Text 2", "type": "body", "description": "Indented body text"},
        {"name": "Quote", "type": "body", "description": "Block quotation"},
        {
            "name": "Intense Quote",
            "type": "body",
            "description": "Emphasized quotation",
        },
        # Lists
        {"name": "List Bullet", "type": "lists", "description": "Bulleted list item"},
        {"name": "List Number", "type": "lists", "description": "Numbered list item"},
        {"name": "List Paragraph", "type": "lists", "description": "List paragraph"},
        # Tables
        {"name": "Table Grid", "type": "tables", "description": "Standard table"},
        {
            "name": "Grid Table 1 Light",
            "type": "tables",
            "description": "Light grid table",
        },
        {
            "name": "Grid Table 4 - Accent 1",
            "type": "tables",
            "description": "Accent table style",
        },
    ]

    if category == "all":
        return all_styles
    return [s for s in all_styles if s["type"] == category]


def _get_powerpoint_styles(category: str) -> List[Dict[str, str]]:
    """Get PowerPoint style definitions."""
    all_styles = [
        {"name": "Title Slide", "type": "heading", "description": "Title slide layout"},
        {"name": "Section Header", "type": "heading", "description": "Section divider"},
        {
            "name": "Title and Content",
            "type": "body",
            "description": "Standard content slide",
        },
        {"name": "Two Content", "type": "body", "description": "Two-column layout"},
        {
            "name": "Comparison",
            "type": "body",
            "description": "Side-by-side comparison",
        },
        {"name": "Blank", "type": "body", "description": "Blank slide"},
    ]

    if category == "all":
        return all_styles
    return [s for s in all_styles if s["type"] == category]


def _get_excel_styles(category: str) -> List[Dict[str, str]]:
    """Get Excel style definitions."""
    all_styles = [
        {"name": "Normal", "type": "body", "description": "Standard cell"},
        {"name": "Heading 1", "type": "heading", "description": "Primary heading"},
        {"name": "Heading 2", "type": "heading", "description": "Secondary heading"},
        {"name": "Title", "type": "heading", "description": "Sheet title"},
        {"name": "Total", "type": "tables", "description": "Total row"},
        {"name": "Accent1", "type": "tables", "description": "Accent color 1"},
    ]

    if category == "all":
        return all_styles
    return [s for s in all_styles if s["type"] == category]


def _extract_brand_colors(tokens: Dict[str, Any]) -> Dict[str, str]:
    """Extract brand colors from tokens."""
    colors = {}

    # Try DTCG format
    if "colors" in tokens and isinstance(tokens["colors"], dict):
        color_group = tokens["colors"]
        if "primary" in color_group:
            primary = color_group["primary"]
            if isinstance(primary, dict) and "$value" in primary:
                colors["primary"] = primary["$value"]
            elif isinstance(primary, str):
                colors["primary"] = primary

        if "secondary" in color_group:
            secondary = color_group["secondary"]
            if isinstance(secondary, dict) and "$value" in secondary:
                colors["secondary"] = secondary["$value"]
            elif isinstance(secondary, str):
                colors["secondary"] = secondary

    # Try legacy format
    if not colors and "colors" in tokens:
        if "palette" in tokens["colors"]:
            palette = tokens["colors"]["palette"]
            if "primary" in palette:
                colors["primary"] = palette["primary"]
            if "secondary" in palette:
                colors["secondary"] = palette["secondary"]

    return colors
