"""
Ribbon configuration builder for pyPhotoAlbum

This module scans classes for methods decorated with @ribbon_action
and automatically builds the ribbon configuration structure.
"""

from typing import Dict, List, Any, Type
from collections import defaultdict


def build_ribbon_config(window_class: Type) -> Dict[str, Any]:
    """
    Extract decorated methods and build ribbon configuration.

    This function scans all methods in the window class and its mixins
    for methods decorated with @ribbon_action, then builds a nested
    configuration structure suitable for the RibbonWidget.

    Args:
        window_class: The MainWindow class with decorated methods

    Returns:
        Dictionary containing the ribbon configuration with structure:
        {
            "TabName": {
                "groups": [
                    {
                        "name": "GroupName",
                        "actions": [
                            {
                                "label": "Button Label",
                                "action": "method_name",
                                "tooltip": "Tooltip text",
                                ...
                            }
                        ]
                    }
                ]
            }
        }
    """
    # Structure to collect actions by tab and group
    tabs: Dict[str, Dict[str, List[Dict[str, Any]]]] = defaultdict(lambda: defaultdict(list))

    # Scan all methods in the class and its bases (mixins)
    for attr_name in dir(window_class):
        try:
            attr = getattr(window_class, attr_name)

            # Check if this attribute has ribbon action metadata
            if hasattr(attr, "_ribbon_action"):
                action_data = attr._ribbon_action

                # Extract tab and group information
                tab_name = action_data["tab"]
                group_name = action_data["group"]

                # Add action to the appropriate tab and group
                tabs[tab_name][group_name].append(
                    {
                        "label": action_data["label"],
                        "action": action_data["action"],
                        "tooltip": action_data["tooltip"],
                        "icon": action_data.get("icon"),
                        "shortcut": action_data.get("shortcut"),
                    }
                )
        except (AttributeError, TypeError):
            # Skip attributes that can't be inspected
            continue

    # Convert to the expected ribbon config format
    ribbon_config = {}

    # Define tab order (tabs will appear in this order)
    tab_order = ["Home", "Insert", "Layout", "Arrange", "Style", "View"]

    # Add tabs in the defined order, then add any remaining tabs
    all_tabs = list(tabs.keys())
    ordered_tabs = [t for t in tab_order if t in all_tabs]
    ordered_tabs.extend([t for t in all_tabs if t not in tab_order])

    for tab_name in ordered_tabs:
        groups_dict = tabs[tab_name]

        # Convert groups dictionary to list format
        groups_list = []

        # Define group order per tab (if needed)
        group_orders = {
            "Home": ["File", "Edit"],
            "Insert": ["Media", "Snapping"],
            "Layout": ["Page", "Templates"],
            "Arrange": ["Align", "Distribute", "Size", "Order", "Transform"],
            "Style": ["Corners", "Border", "Effects", "Frame", "Presets"],
            "View": ["Zoom", "Guides"],
        }

        # Get the group order for this tab, or use alphabetical
        if tab_name in group_orders:
            group_order = group_orders[tab_name]
            # Add any groups not in the defined order
            all_groups = list(groups_dict.keys())
            group_order.extend([g for g in all_groups if g not in group_order])
        else:
            group_order = sorted(groups_dict.keys())

        for group_name in group_order:
            if group_name in groups_dict:
                actions = groups_dict[group_name]
                groups_list.append({"name": group_name, "actions": actions})

        ribbon_config[tab_name] = {"groups": groups_list}

    return ribbon_config


def get_keyboard_shortcuts(window_class: Type) -> Dict[str, str]:
    """
    Extract keyboard shortcuts from decorated methods.

    Args:
        window_class: The MainWindow class with decorated methods

    Returns:
        Dictionary mapping shortcut strings to method names
        Example: {'Ctrl+N': 'new_project', 'Ctrl+S': 'save_project'}
    """
    shortcuts = {}

    for attr_name in dir(window_class):
        try:
            attr = getattr(window_class, attr_name)

            if hasattr(attr, "_ribbon_action"):
                action_data = attr._ribbon_action
                shortcut = action_data.get("shortcut")

                if shortcut:
                    shortcuts[shortcut] = action_data["action"]
        except (AttributeError, TypeError):
            continue

    return shortcuts


def validate_ribbon_config(config: Dict[str, Any]) -> List[str]:
    """
    Validate the ribbon configuration structure.

    Args:
        config: The ribbon configuration dictionary

    Returns:
        List of validation error messages (empty if valid)
    """
    errors = []

    if not isinstance(config, dict):
        errors.append("Config must be a dictionary")
        return errors

    for tab_name, tab_data in config.items():
        if not isinstance(tab_data, dict):
            errors.append(f"Tab '{tab_name}' data must be a dictionary")
            continue

        if "groups" not in tab_data:
            errors.append(f"Tab '{tab_name}' missing 'groups' key")
            continue

        groups = tab_data["groups"]
        if not isinstance(groups, list):
            errors.append(f"Tab '{tab_name}' groups must be a list")
            continue

        for i, group in enumerate(groups):
            if not isinstance(group, dict):
                errors.append(f"Tab '{tab_name}' group {i} must be a dictionary")
                continue

            if "name" not in group:
                errors.append(f"Tab '{tab_name}' group {i} missing 'name'")

            if "actions" not in group:
                errors.append(f"Tab '{tab_name}' group {i} missing 'actions'")
                continue

            actions = group["actions"]
            if not isinstance(actions, list):
                errors.append(f"Tab '{tab_name}' group {i} actions must be a list")
                continue

            for j, action in enumerate(actions):
                if not isinstance(action, dict):
                    errors.append(f"Tab '{tab_name}' group {i} action {j} must be a dictionary")
                    continue

                required_keys = ["label", "action", "tooltip"]
                for key in required_keys:
                    if key not in action:
                        errors.append(f"Tab '{tab_name}' group {i} action {j} missing '{key}'")

    return errors


def print_ribbon_summary(config: Dict[str, Any]):
    """
    Print a summary of the ribbon configuration.

    Args:
        config: The ribbon configuration dictionary
    """
    print("\n=== Ribbon Configuration Summary ===\n")

    total_tabs = len(config)
    total_groups = sum(len(tab_data["groups"]) for tab_data in config.values())
    total_actions = sum(len(group["actions"]) for tab_data in config.values() for group in tab_data["groups"])

    print(f"Total Tabs: {total_tabs}")
    print(f"Total Groups: {total_groups}")
    print(f"Total Actions: {total_actions}\n")

    for tab_name, tab_data in config.items():
        print(f"📑 {tab_name}")
        for group in tab_data["groups"]:
            print(f"  📦 {group['name']} ({len(group['actions'])} actions)")
            for action in group["actions"]:
                shortcut = f" ({action['shortcut']})" if action.get("shortcut") else ""
                print(f"    • {action['label']}{shortcut}")
        print()
