import json
from logging import Logger
from typing import Any, Optional

from rich.console import Console
from rich.panel import Panel
from rich.pretty import Pretty


def _determine_object_title(obj: Any) -> str:
    """
    Determine a descriptive title for an object based on its type.
    
    Args:
        obj: Object to determine title for
        
    Returns:
        String title for the object
    """
    if isinstance(obj, list):
        if obj:
            if isinstance(obj[0], dict):
                return "Dict"
            return "Object"
        return "List"
    elif isinstance(obj, dict):
        return "Dict"
    else:
        return obj.__class__.__name__ if hasattr(obj, "__class__") else "Object"


def _create_panel(obj: Any, title: str, border_style: str = "blue") -> Panel:
    """
    Create a Rich Panel for displaying an object.
    
    Args:
        obj: Object to display
        title: Title for the panel
        border_style: Border style color
        
    Returns:
        Rich Panel instance
    """
    return Panel(
        Pretty(obj, expand_all=True, indent_guides=True),
        border_style=border_style,
        title=title,
        title_align="left",
        padding=(1, 2),
        expand=False,
    )


def _format_plain_text(obj: Any, title: str) -> str:
    """
    Format an object as plain text JSON.
    
    Args:
        obj: Object to format
        title: Title for the output
        
    Returns:
        Formatted text string
    """
    text_lines = [f"{title}:"]
    
    if isinstance(obj, list):
        if obj and isinstance(obj[0], dict):
            for i, item in enumerate(obj):
                text_lines.append(f"Object {i+1}:")
                text_lines.append(json.dumps(item, indent=2, default=str))
        else:
            text_lines.append(json.dumps(obj, indent=2, default=str))
    else:
        text_lines.append(json.dumps(obj, indent=2, default=str))
    
    return "\n".join(text_lines)


def pprint_obj(
    obj: Any,
    *,
    debug: bool = False,
    console: Optional[Console] = None,
    logger: Optional[Logger] = None,
    log_level: str = "DEBUG",
    **kwargs: Any,
) -> None:
    """
    Print Python primitive objects (dict, list, etc.) respecting rich and debug settings.
    
    This is a core fallback function that handles only Python object-like primitives.
    For Pydantic models, use pprint_model from pytools.pydantic.debug.pprint_model.

    Args:
        obj: Python object to print (dict, list, or any object)
        debug: Override debug flag
        console: Optional Rich console to use; if None, plain text is used
        logger: Optional Logger to use
        log_level: Log level for logger
        **kwargs: Additional keyword arguments (ignored, kept for API compatibility)
    """
    if not debug:
        return

    object_title = _determine_object_title(obj)

    # --- CASE 1: Rich console available ---
    if console:
        if isinstance(obj, list) and obj and isinstance(obj[0], dict):
            # List of dicts: print each dict in a separate panel
            for item in obj:
                panel = _create_panel(item, object_title, border_style="blue")
                console.print(panel)
        else:
            # Single object: determine border style based on type
            border_style = "blue" if isinstance(obj, dict) else "green"
            panel = _create_panel(obj, object_title, border_style=border_style)
            console.print(panel)
        return

    # --- CASE 2: No console → plain text output ---
    text = _format_plain_text(obj, object_title)

    # --- CASE 3: Logger or print fallback ---
    if logger:
        logger.log(log_level, text)
    else:
        print(text)