"""
iTerm2 Profile Management for Claude Team MCP

Handles creation and customization of iTerm2 profiles for managed Claude sessions.
Includes automatic dark/light mode detection and consistent visual styling.
"""

import logging
import re
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from iterm2.color import Color as ItermColor
    from iterm2.connection import Connection as ItermConnection
    from iterm2.profile import LocalWriteOnlyProfile

from .subprocess_cache import cached_system_profiler

logger = logging.getLogger("maniple.profile")


# =============================================================================
# Constants
# =============================================================================

# Profile identifier - used to find or create our managed profile
PROFILE_NAME = "claude-team"

# Font configuration - Source Code Pro preferred, Menlo as fallback
FONT_PRIMARY = "Source Code Pro"
FONT_FALLBACK = "Menlo"
FONT_SIZE = 12


# =============================================================================
# Color Schemes
# =============================================================================

# Light mode color scheme - optimized for readability
COLORS_LIGHT = {
    "foreground": (30, 30, 30),         # Near-black text
    "background": (255, 255, 255),       # White background
    "cursor": (0, 122, 255),             # Blue cursor
    "selection": (179, 215, 255),        # Light blue selection
    "bold": (0, 0, 0),                   # Black for bold text
    # ANSI colors (normal)
    "ansi_black": (0, 0, 0),
    "ansi_red": (194, 54, 33),
    "ansi_green": (37, 137, 58),
    "ansi_yellow": (173, 124, 36),
    "ansi_blue": (66, 133, 244),
    "ansi_magenta": (162, 73, 162),
    "ansi_cyan": (23, 162, 184),
    "ansi_white": (255, 255, 255),
}

# Dark mode color scheme - optimized for low-light environments
COLORS_DARK = {
    "foreground": (229, 229, 229),       # Light gray text
    "background": (30, 30, 30),          # Near-black background
    "cursor": (66, 133, 244),            # Blue cursor
    "selection": (62, 68, 81),           # Dark gray selection
    "bold": (255, 255, 255),             # White for bold text
    # ANSI colors (normal)
    "ansi_black": (0, 0, 0),
    "ansi_red": (255, 85, 85),
    "ansi_green": (80, 200, 120),
    "ansi_yellow": (255, 204, 0),
    "ansi_blue": (100, 149, 237),
    "ansi_magenta": (218, 112, 214),
    "ansi_cyan": (0, 206, 209),
    "ansi_white": (255, 255, 255),
}


# =============================================================================
# Screen Dimension Calculation
# =============================================================================


def calculate_screen_dimensions() -> tuple[int, int]:
    """
    Calculate terminal columns/rows to fill the screen.

    Uses system_profiler to get screen resolution and calculates appropriate
    terminal dimensions based on Menlo 12pt font cell size.

    Returns:
        Tuple of (columns, rows) for a screen-filling terminal window
    """
    try:
        # Use cached system_profiler to avoid repeated slow calls
        stdout = cached_system_profiler("SPDisplaysDataType")
        if stdout is None:
            logger.warning("system_profiler failed, using default dimensions")
            return (200, 60)

        # Parse resolution from output like "Resolution: 3024 x 1964"
        match = re.search(r"Resolution: (\d+) x (\d+)", stdout)
        if not match:
            logger.warning("Could not parse screen resolution, using defaults")
            return (200, 60)

        screen_w, screen_h = int(match.group(1)), int(match.group(2))

        # Detect Retina display (2x scale factor)
        scale = 2 if "Retina" in stdout else 1
        logical_w = screen_w // scale
        logical_h = screen_h // scale

        # Subtract margins for window chrome:
        # - ~20px for window borders
        # - ~100px for menu bar + dock + title bar
        usable_w = logical_w - 20
        usable_h = logical_h - 100

        # Menlo 12pt cell size (approximately)
        cell_w, cell_h = 7.2, 14.0

        cols = int(usable_w / cell_w)
        rows = int(usable_h / cell_h)

        logger.debug(
            f"Screen {screen_w}x{screen_h} (scale {scale}) -> "
            f"terminal {cols}x{rows}"
        )
        return (cols, rows)

    except Exception as e:
        logger.warning(f"Failed to calculate screen dimensions: {e}")
        return (200, 60)


# =============================================================================
# Appearance Mode Detection
# =============================================================================


async def detect_appearance_mode(connection: "ItermConnection") -> str:
    """
    Detect the current macOS appearance mode (light or dark).

    Uses iTerm2's effective theme to determine the system appearance.
    Falls back to 'dark' if detection fails.

    Args:
        connection: Active iTerm2 connection

    Returns:
        'light' or 'dark' based on system appearance
    """
    try:
        from iterm2.app import async_get_app

        # Get the app object to query effective theme
        app = await async_get_app(connection)
        if app is None:
            logger.warning("Could not get iTerm2 app, defaulting to dark")
            return "dark"

        # iTerm2's effective_theme returns a list of theme components
        # Common values include 'dark', 'light', 'automatic'
        theme = await app.async_get_variable("effectiveTheme")

        if theme and isinstance(theme, str):
            # effectiveTheme is a string like "dark" or "light"
            theme_lower = theme.lower()
            if "light" in theme_lower:
                return "light"
            elif "dark" in theme_lower:
                return "dark"

        # If theme is a list (some iTerm2 versions), check for dark indicators
        if theme and isinstance(theme, list):
            for component in theme:
                if isinstance(component, str) and "dark" in component.lower():
                    return "dark"
            return "light"

        logger.warning(f"Could not parse theme '{theme}', defaulting to dark")
        return "dark"

    except Exception as e:
        logger.warning(f"Failed to detect appearance mode: {e}, defaulting to dark")
        return "dark"


def get_colors_for_mode(mode: str) -> dict:
    """
    Get the color scheme dictionary for the specified appearance mode.

    Args:
        mode: Either 'light' or 'dark'

    Returns:
        Dictionary of color names to RGB tuples
    """
    if mode == "light":
        return COLORS_LIGHT.copy()
    return COLORS_DARK.copy()


# =============================================================================
# Profile Management
# =============================================================================


async def get_or_create_profile(connection: "ItermConnection") -> str:
    """
    Get or create the claude-team iTerm2 profile.

    Checks if a profile named 'claude-team' exists. If not, creates it
    with sensible defaults including font configuration and color scheme
    based on the current system appearance mode.

    Args:
        connection: Active iTerm2 connection

    Returns:
        The profile name (PROFILE_NAME constant)

    Note:
        This function creates a partial profile. The caller should
        use create_session_customizations() to apply per-session
        customizations like tab color and title.
    """
    from iterm2.profile import LocalWriteOnlyProfile as LWOProfile
    from iterm2.profile import PartialProfile

    # Get all existing profiles
    all_profiles = await PartialProfile.async_query(connection)
    profile_names = [p.name for p in all_profiles if p.name]

    # Check if our profile already exists
    if PROFILE_NAME in profile_names:
        logger.debug(f"Profile '{PROFILE_NAME}' already exists")
        return PROFILE_NAME

    logger.info(f"Creating new profile '{PROFILE_NAME}'")

    # Find a suitable source profile (prefer Default, then first available)
    source_profile = None
    for profile in all_profiles:
        if profile.name == "Default":
            source_profile = profile
            break

    if not source_profile and all_profiles:
        source_profile = all_profiles[0]

    if not source_profile:
        raise RuntimeError("No profiles found to use as template")

    # Create a new profile with our name
    # iTerm2 doesn't have a direct "create profile" API, so we use
    # LocalWriteOnlyProfile to define settings and create a session with it

    # Detect appearance mode for initial colors
    mode = await detect_appearance_mode(connection)
    colors = get_colors_for_mode(mode)

    # Create the profile settings
    profile = LWOProfile()
    profile.set_name(PROFILE_NAME)

    # Font configuration - use async_set methods for font
    # Try Source Code Pro first, fall back to Menlo
    try:
        profile.set_normal_font(f"{FONT_PRIMARY} {FONT_SIZE}")
    except Exception:
        logger.warning(f"Font '{FONT_PRIMARY}' not available, using '{FONT_FALLBACK}'")
        profile.set_normal_font(f"{FONT_FALLBACK} {FONT_SIZE}")

    # Apply color scheme
    _apply_colors_to_profile(profile, colors)

    # Window settings - use tabs, not fullscreen
    profile.set_use_tab_color(True)
    profile.set_smart_cursor_color(True)

    # The profile will be created implicitly when a session uses it.
    # For now, we need to ensure it exists by using create_profile_with_api
    # or by having a session use it.

    # Note: iTerm2's Python API doesn't have a direct "create profile from scratch" method.
    # The profile will be created when first used. For persistence, users should
    # save the profile via iTerm2's UI or use the JSON profile import feature.

    logger.info(
        f"Profile '{PROFILE_NAME}' configured with {FONT_PRIMARY} {FONT_SIZE}pt, "
        f"{mode} mode colors"
    )

    return PROFILE_NAME


async def apply_appearance_colors(
    profile: "LocalWriteOnlyProfile",
    connection: "ItermConnection",
) -> None:
    """
    Apply current appearance mode colors to a session profile.

    Detects the current macOS light/dark mode and applies the appropriate
    color scheme to the given profile. Call this when creating per-session
    customizations to ensure workers match the current system appearance.

    Args:
        profile: The LocalWriteOnlyProfile to modify
        connection: Active iTerm2 connection (needed for appearance detection)
    """
    mode = await detect_appearance_mode(connection)
    colors = get_colors_for_mode(mode)
    _apply_colors_to_profile(profile, colors)


def _apply_colors_to_profile(
    profile: "LocalWriteOnlyProfile",
    colors: dict,
) -> None:
    """
    Apply a color scheme to a profile.

    Helper function that sets all color-related profile properties
    from a color scheme dictionary.

    Args:
        profile: The profile to modify
        colors: Dictionary of color names to RGB tuples
    """
    from iterm2.color import Color

    def rgb_to_color(rgb: tuple[int, int, int]) -> "ItermColor":
        return Color(rgb[0], rgb[1], rgb[2])

    # Basic colors
    if "foreground" in colors:
        profile.set_foreground_color(rgb_to_color(colors["foreground"]))
    if "background" in colors:
        profile.set_background_color(rgb_to_color(colors["background"]))
    if "cursor" in colors:
        profile.set_cursor_color(rgb_to_color(colors["cursor"]))
    if "selection" in colors:
        profile.set_selection_color(rgb_to_color(colors["selection"]))
    if "bold" in colors:
        profile.set_bold_color(rgb_to_color(colors["bold"]))

    # ANSI colors
    ansi_color_setters = [
        ("ansi_black", profile.set_ansi_0_color),
        ("ansi_red", profile.set_ansi_1_color),
        ("ansi_green", profile.set_ansi_2_color),
        ("ansi_yellow", profile.set_ansi_3_color),
        ("ansi_blue", profile.set_ansi_4_color),
        ("ansi_magenta", profile.set_ansi_5_color),
        ("ansi_cyan", profile.set_ansi_6_color),
        ("ansi_white", profile.set_ansi_7_color),
    ]

    for color_name, setter in ansi_color_setters:
        if color_name in colors:
            setter(rgb_to_color(colors[color_name]))

