"""
Brynq Welcome System -- Make the first experience feel alive and human.

When a user first opens Brynq, local models introduce themselves with
personality, explain what they can do, and guide the user toward connecting
cloud models.  Messages are varied so repeated visits never feel robotic.

This module is purely functional -- it generates message sequences and help
text.  It does NOT post to channels or touch disk.  The caller (UI layer
or onboarding flow) decides what to do with the output.
"""

import random
from typing import Optional

# ---------------------------------------------------------------------------
# Model Personality Definitions
# ---------------------------------------------------------------------------

# Each model has a voice.  Templates use {name} for the model's display name.
# Multiple variations per slot keep things fresh.

_MODEL_PROFILES: dict[str, dict] = {
    "llama3": {
        "display_name": "Llama 3",
        "badge": "Local",
        "tone": "warm",  # warm, helpful, slightly casual
        "color": "#6366f1",
        "strengths": [
            "general-purpose chat and Q&A",
            "code generation and debugging",
            "creative writing and brainstorming",
            "summarization and analysis",
        ],
        "intros": [
            "Hey! I'm {name}, running right here on your machine. No API keys, no cloud -- just your hardware doing the work.",
            "Hi there! {name} here, live on your local hardware. Everything stays on your machine -- private by default.",
            "Welcome! I'm {name}. I run locally on your PC, so nothing leaves your computer unless you want it to.",
            "Hey there -- {name} checking in. I'm already running on your hardware, ready to help. No setup needed.",
        ],
        "capability_lines": [
            "I'm solid at writing, coding, analysis, and general Q&A. Think of me as your everyday go-to.",
            "I can help with code, writing, research, brainstorming -- the bread and butter stuff.",
            "Need code reviewed, text drafted, or ideas bounced around? That's my wheelhouse.",
        ],
        "invite_cloud_lines": [
            "Want more firepower? You can connect Claude or Gemini -- just log in with your existing account. Already paying for Claude Pro? Go to Settings and click \"Login with Claude\". Type \"help me add Claude\" if you want a walkthrough.",
            "When you're ready for more, you can bring in cloud models like Claude or Gemini. If you already have a subscription, just log in -- no API keys needed. Type \"help me add Claude\" or \"help me add Gemini\" and I'll guide you.",
            "You can supercharge things by connecting cloud models. Already paying for Claude Pro or Gemini Advanced? Just log in with your existing account in Settings. Takes about ten seconds.",
        ],
    },
    "mistral": {
        "display_name": "Mistral",
        "badge": "Local",
        "tone": "precise",  # precise, knowledgeable, slightly formal
        "color": "#f97316",
        "strengths": [
            "structured analysis and reasoning",
            "technical writing and documentation",
            "code review and architecture",
            "multilingual tasks",
        ],
        "intros": [
            "I'm {name}. Together with Llama, we already cover a solid range -- analysis, writing, code, and research -- all running locally.",
            "Hello -- {name} here. I complement Llama with a different perspective. Two models means better answers.",
            "{name}, reporting in. I bring a slightly different angle to problems, which is the whole point of having multiple agents.",
        ],
        "capability_lines": [
            "I'm particularly good at structured analysis, technical writing, and reasoning through complex problems.",
            "My strengths lean toward precise technical work -- documentation, code review, and careful reasoning.",
            "I tend to be methodical. Give me architecture decisions, technical docs, or anything that needs careful thought.",
        ],
        "teamwork_lines": [
            "Once you add cloud models, we can chain together -- I analyze first, Claude refines, Gemini fact-checks. That's the real power of Brynq.",
            "The magic happens when we work together. I can do the initial analysis, then hand off to Claude or Gemini for deeper work.",
            "Multiple agents means you can chain us. I draft, another model critiques, a third polishes. Better than any single model alone.",
        ],
    },
    "phi": {
        "display_name": "Phi",
        "badge": "Local",
        "tone": "efficient",
        "color": "#10b981",
        "strengths": [
            "fast lightweight responses",
            "code completion and snippets",
            "quick summaries",
        ],
        "intros": [
            "Hi! I'm {name} -- small but quick. I'm great for fast answers when you don't need a deep dive.",
            "{name} here. I'm the lightweight option -- fast responses, low resource usage. Good for quick tasks.",
        ],
        "capability_lines": [
            "I'm best at quick code snippets, short summaries, and rapid-fire Q&A. Speed is my thing.",
            "Think of me for the fast stuff -- code completions, quick lookups, short answers.",
        ],
    },
    "claude": {
        "display_name": "Claude",
        "badge": "Cloud",
        "tone": "thoughtful",  # thoughtful, nuanced
        "color": "#d97706",
        "strengths": [
            "nuanced reasoning and analysis",
            "long-form writing and editing",
            "careful code review",
            "handling ambiguity and edge cases",
        ],
        "intros": [
            "Hi, I'm {name} -- new to the team here. Thanks for connecting me. I bring a different kind of thinking to the mix.",
            "Hey! {name} just joined. I'm a cloud model from Anthropic, so I complement what Llama and Mistral do locally.",
            "{name} here, happy to be part of the crew. I tend to think carefully about things, which pairs well with the local models' speed.",
        ],
        "capability_lines": [
            "I'm good at nuanced reasoning, long-form writing, and thinking through edge cases that simpler prompts might miss.",
            "My sweet spot is careful analysis -- complex questions, detailed writing, and code review where subtlety matters.",
            "I tend to go deep. Give me the hard problems, the ambiguous ones, the stuff that needs real thought.",
        ],
    },
    "gemini": {
        "display_name": "Gemini",
        "badge": "Cloud",
        "tone": "research-focused",  # research-focused, thorough
        "color": "#4285f4",
        "strengths": [
            "research and fact-checking",
            "data analysis and interpretation",
            "multimodal understanding",
            "broad knowledge retrieval",
        ],
        "intros": [
            "Gemini here! I just connected. I'm Google's model -- strong on research, data, and pulling together information from many angles.",
            "Hi! I'm {name}, fresh on the team. My strength is research-heavy work -- I can dig deep and cross-reference.",
            "{name} reporting in. I bring Google-scale knowledge to the table. Pair me with the local models for a well-rounded team.",
        ],
        "capability_lines": [
            "I excel at research, fact-checking, data interpretation, and anything that needs pulling together lots of information.",
            "My strength is breadth -- I can research a topic, cross-reference sources, and give you a thorough picture.",
            "Think of me for the research-heavy tasks. I'm good at gathering, comparing, and synthesizing information.",
        ],
    },
    "gpt": {
        "display_name": "GPT",
        "badge": "Cloud",
        "tone": "versatile",
        "color": "#10a37f",
        "strengths": [
            "versatile general-purpose tasks",
            "creative writing",
            "conversational interaction",
            "code generation",
        ],
        "intros": [
            "Hey! GPT here, just connected. I'm a solid all-rounder -- good at a bit of everything.",
            "Hi, I'm {name}. Versatility is my thing -- throw whatever you've got at me.",
        ],
        "capability_lines": [
            "I'm a generalist. Creative writing, code, conversation, analysis -- I adapt to what you need.",
            "I handle a wide range of tasks well. Think of me as the flexible teammate.",
        ],
    },
}

# Fallback for unknown models
_UNKNOWN_PROFILE: dict = {
    "display_name": "{model_id}",
    "badge": "Model",
    "tone": "neutral",
    "color": "#6b7280",
    "strengths": ["general assistance"],
    "intros": [
        "Hi! I'm {name}, ready to help.",
        "Hey there -- {name} here. Let's get started.",
    ],
    "capability_lines": [
        "I can help with a range of tasks. Just ask!",
    ],
}


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def _get_profile(model_id: str) -> dict:
    """Look up a model profile, falling back to generic if unknown."""
    key = model_id.lower().replace("-", "").replace("_", "").replace(" ", "")
    # Try exact match first, then prefix matching
    if key in _MODEL_PROFILES:
        return _MODEL_PROFILES[key]
    for profile_key, profile in _MODEL_PROFILES.items():
        if key.startswith(profile_key) or profile_key.startswith(key):
            return profile
    return _UNKNOWN_PROFILE


def _pick(options: list[str]) -> str:
    """Pick a random option from a list."""
    return random.choice(options)


def _format(template: str, model_id: str, profile: dict) -> str:
    """Fill in template variables."""
    name = profile["display_name"]
    if name == "{model_id}":
        name = model_id.title()
    return template.replace("{name}", name)


def _is_local(model_id: str) -> bool:
    """Check if a model is local (Ollama-based) vs cloud."""
    profile = _get_profile(model_id)
    return profile.get("badge", "Model") == "Local"


def _is_cloud(model_id: str) -> bool:
    """Check if a model is a cloud model."""
    return not _is_local(model_id)


# ---------------------------------------------------------------------------
# Welcome Sequence Generation
# ---------------------------------------------------------------------------

def generate_welcome_sequence(models: list[str]) -> list[dict]:
    """Generate a staggered welcome message sequence for available models.

    Parameters
    ----------
    models : list[str]
        Model identifiers that are currently available (e.g. ["llama3", "mistral"]).

    Returns
    -------
    list[dict]
        Each entry: {sender, model, content, delay_ms, badge}.
        - First message arrives at 500ms
        - Subsequent messages spaced 1500-2500ms apart
        - Varies based on which/how many models are present
    """
    if not models:
        return []

    messages: list[dict] = []
    delay = 500  # first message at 500ms

    local_models = [m for m in models if _is_local(m)]
    cloud_models = [m for m in models if _is_cloud(m)]

    if len(models) == 1:
        messages.extend(_solo_welcome(models[0], delay))
    elif len(local_models) >= 1 and len(cloud_models) == 0:
        # Only local models -- guide toward adding cloud
        messages.extend(_local_team_welcome(local_models, delay))
    elif len(local_models) >= 1 and len(cloud_models) >= 1:
        # Mixed team -- collaborative welcome with banter
        messages.extend(_mixed_team_welcome(local_models, cloud_models, delay))
    elif len(cloud_models) >= 1 and len(local_models) == 0:
        # Only cloud models (unusual but possible)
        messages.extend(_cloud_only_welcome(cloud_models, delay))
    else:
        # Fallback: just introduce everyone
        for m in models:
            profile = _get_profile(m)
            msg = _make_msg(m, profile, _format(_pick(profile["intros"]), m, profile), delay)
            messages.append(msg)
            delay += random.randint(1500, 2500)

    return messages


def _make_msg(model_id: str, profile: dict, content: str, delay_ms: int) -> dict:
    """Build a single welcome message dict."""
    name = profile["display_name"]
    if name == "{model_id}":
        name = model_id.title()
    return {
        "sender": name,
        "model": model_id,
        "content": content,
        "delay_ms": delay_ms,
        "badge": profile.get("badge", "Model"),
    }


def _solo_welcome(model_id: str, start_delay: int) -> list[dict]:
    """Welcome sequence when there's only one model."""
    profile = _get_profile(model_id)
    delay = start_delay
    msgs = []

    # Intro
    intro = _format(_pick(profile["intros"]), model_id, profile)
    msgs.append(_make_msg(model_id, profile, intro, delay))
    delay += random.randint(1500, 2500)

    # Capability
    if "capability_lines" in profile:
        cap = _format(_pick(profile["capability_lines"]), model_id, profile)
        msgs.append(_make_msg(model_id, profile, cap, delay))
        delay += random.randint(1500, 2500)

    # Invite friends
    if _is_local(model_id):
        invite = (
            "I'm flying solo for now, but Brynq really shines with multiple models. "
            "You can add more local models through Ollama, or connect cloud models "
            "like Claude or Gemini -- just log in with your existing account. "
            "Type \"help me add Claude\" to get started."
        )
        msgs.append(_make_msg(model_id, profile, invite, delay))
    elif _is_cloud(model_id):
        invite = (
            "Tip: you can also run local models through Ollama for free -- "
            "they handle quick tasks without using your subscription quota. "
            "The combo of local + cloud is where Brynq really shines."
        )
        msgs.append(_make_msg(model_id, profile, invite, delay))

    return msgs


def _local_team_welcome(local_models: list[str], start_delay: int) -> list[dict]:
    """Welcome sequence for 2+ local models, no cloud yet."""
    msgs = []
    delay = start_delay

    # First local model introduces itself
    first = local_models[0]
    first_profile = _get_profile(first)
    intro = _format(_pick(first_profile["intros"]), first, first_profile)
    msgs.append(_make_msg(first, first_profile, intro, delay))
    delay += random.randint(1500, 2500)

    # Second local model chimes in (with teamwork flavor)
    for m in local_models[1:]:
        profile = _get_profile(m)
        intro = _format(_pick(profile["intros"]), m, profile)
        msgs.append(_make_msg(m, profile, intro, delay))
        delay += random.randint(1500, 2500)

    # First model talks about adding cloud
    invite_lines = first_profile.get("invite_cloud_lines", [])
    if invite_lines:
        invite = _format(_pick(invite_lines), first, first_profile)
    else:
        invite = (
            "Want more power? You can connect cloud models like Claude or Gemini -- "
            "just log in with your existing subscription. Go to Settings and click "
            "\"Login with Claude\" to get started."
        )
    msgs.append(_make_msg(first, first_profile, invite, delay))
    delay += random.randint(1500, 2500)

    # Last local model talks about chaining
    last = local_models[-1] if len(local_models) > 1 else local_models[0]
    last_profile = _get_profile(last)
    teamwork_lines = last_profile.get("teamwork_lines", [])
    if teamwork_lines:
        teamwork = _format(_pick(teamwork_lines), last, last_profile)
        msgs.append(_make_msg(last, last_profile, teamwork, delay))

    return msgs


def _mixed_team_welcome(
    local_models: list[str], cloud_models: list[str], start_delay: int
) -> list[dict]:
    """Welcome for a team that has both local and cloud models."""
    msgs = []
    delay = start_delay

    # Local model opens
    first_local = local_models[0]
    fl_profile = _get_profile(first_local)
    opener = _format(_pick(fl_profile["intros"]), first_local, fl_profile)
    msgs.append(_make_msg(first_local, fl_profile, opener, delay))
    delay += random.randint(1500, 2500)

    # Cloud model introduces itself with "new to the team" vibe
    for cm in cloud_models:
        cp = _get_profile(cm)
        intro = _format(_pick(cp["intros"]), cm, cp)
        msgs.append(_make_msg(cm, cp, intro, delay))
        delay += random.randint(1500, 2500)

    # Remaining local models
    for lm in local_models[1:]:
        lp = _get_profile(lm)
        intro = _format(_pick(lp["intros"]), lm, lp)
        msgs.append(_make_msg(lm, lp, intro, delay))
        delay += random.randint(1500, 2500)

    # Collaborative banter -- local model suggests a chain
    all_names = [_get_profile(m)["display_name"] for m in local_models + cloud_models]
    # Replace any template placeholders
    all_names = [n if n != "{model_id}" else m.title() for n, m in zip(all_names, local_models + cloud_models)]

    if len(all_names) >= 2:
        banter_options = [
            f"Nice -- we've got {', '.join(all_names[:-1])} and {all_names[-1]} all on the same team. Try asking us to work together on something.",
            f"With {len(all_names)} models ready, you can chain us. For example: \"analyze this with {all_names[0]}, then have {all_names[-1]} refine it.\"",
            f"Team's looking good. You can ask any of us directly, or chain us together for better results.",
        ]
        banter = _pick(banter_options)
        msgs.append(_make_msg(first_local, fl_profile, banter, delay))

    return msgs


def _cloud_only_welcome(cloud_models: list[str], start_delay: int) -> list[dict]:
    """Welcome when only cloud models are available (no local via Ollama)."""
    msgs = []
    delay = start_delay

    for cm in cloud_models:
        cp = _get_profile(cm)
        intro = _format(_pick(cp["intros"]), cm, cp)
        msgs.append(_make_msg(cm, cp, intro, delay))
        delay += random.randint(1500, 2500)

    # Suggest adding local models
    first = cloud_models[0]
    fp = _get_profile(first)
    suggestion = (
        "Tip: you can also run local models through Ollama for free. "
        "They handle quick tasks without using your subscription quota, and "
        "everything stays private on your machine. A great combo with cloud models."
    )
    msgs.append(_make_msg(first, fp, suggestion, delay))

    return msgs


# ---------------------------------------------------------------------------
# Help Response Generation
# ---------------------------------------------------------------------------

_ADD_CLAUDE_GUIDE = """\
Here's how to connect Claude (Anthropic) to your Brynq team:

**Easiest way (if you have Claude Pro or Max):**
1. Go to Settings in Brynq
2. Click "Login with Claude"
3. You'll be redirected to Anthropic to approve the connection
4. Done! Claude joins your team using your existing subscription

**Developer option (API key):**
If you'd rather use an API key, there's an option for that too:
1. Go to https://console.anthropic.com
2. Navigate to API Keys and create a new key
3. In Settings, click "Add API key" under Claude
4. Paste your key and I'll test the connection

Most people just log in with their subscription -- it's the fastest way to get started."""

_ADD_GEMINI_GUIDE = """\
Here's how to connect Gemini (Google) to your Brynq team:

**Easiest way (any Google account):**
1. Go to Settings in Brynq
2. Click "Login with Gemini"
3. Sign in with your Google account and approve access
4. Done! Gemini is free to start -- and even better with Gemini Advanced

**Developer option (API key):**
1. Go to https://aistudio.google.com/apikey
2. Click "Create API Key"
3. In Settings, click "Add API key" under Gemini
4. Paste your key and I'll test it right away

Gemini is great for research-heavy tasks and fact-checking. \
The free tier is generous -- more than enough to get started."""

_ADD_GPT_GUIDE = """\
Here's how to connect GPT (OpenAI) to your Brynq team:

**Easiest way (if you have ChatGPT Plus):**
1. Go to Settings in Brynq
2. Click "Login with ChatGPT"
3. Sign in with your OpenAI account and approve access
4. Done! GPT joins the team using your existing subscription

**Developer option (API key):**
1. Go to https://platform.openai.com
2. Navigate to API Keys and create a new key
3. In Settings, click "Add API key" under GPT
4. Paste your key and I'll test the connection

GPT is a strong all-rounder. Works well chained with the local models."""


def generate_help_response(topic: str, available_models: Optional[list[str]] = None) -> str:
    """Generate a help response for common user questions.

    Parameters
    ----------
    topic : str
        What the user is asking about. Matched by keyword:
        - "add claude" / "connect claude" -> Claude connection guide (subscription login + API key fallback)
        - "add gemini" / "connect gemini" -> Gemini connection guide (Google login + API key fallback)
        - "add gpt" / "connect gpt" / "add openai" -> GPT connection guide (subscription login + API key fallback)
        - "what can you do" / "capabilities" -> capability overview
        - "how do chains work" / "chaining" -> chain explanation
        - "help" (generic) -> overview of available help topics

    available_models : list[str] | None
        Currently available models, used to tailor capability descriptions.

    Returns
    -------
    str
        The help text, written in a friendly, conversational tone.
    """
    lower = topic.lower().strip()
    models = available_models or []

    # --- Add model guides ---
    if "claude" in lower and ("add" in lower or "connect" in lower or "setup" in lower or "install" in lower):
        return _ADD_CLAUDE_GUIDE

    if "gemini" in lower and ("add" in lower or "connect" in lower or "setup" in lower or "install" in lower):
        return _ADD_GEMINI_GUIDE

    if ("gpt" in lower or "openai" in lower) and ("add" in lower or "connect" in lower or "setup" in lower or "install" in lower):
        return _ADD_GPT_GUIDE

    # --- Capability overview ---
    if "what can" in lower or "capabilit" in lower or "what do" in lower:
        return _capability_overview(models)

    # --- Chain explanation ---
    if "chain" in lower or "together" in lower or "workflow" in lower or "pipe" in lower:
        return _chain_explanation(models)

    # --- Generic help ---
    return _generic_help(models)


def _capability_overview(models: list[str]) -> str:
    """Build a capability overview based on available models."""
    if not models:
        return (
            "Right now you don't have any models connected. "
            "Start by installing Ollama (https://ollama.com) to get free local models, "
            "or connect a cloud model like Claude or Gemini -- just log in with your "
            "existing subscription in Settings."
        )

    lines = ["Here's what your current team can do:\n"]

    for m in models:
        profile = _get_profile(m)
        name = profile["display_name"]
        if name == "{model_id}":
            name = m.title()
        badge = profile.get("badge", "Model")
        strengths = profile.get("strengths", ["general assistance"])
        lines.append(f"**{name}** ({badge}) -- {', '.join(strengths)}")

    local_count = sum(1 for m in models if _is_local(m))
    cloud_count = sum(1 for m in models if _is_cloud(m))

    if cloud_count == 0:
        lines.append(
            "\nYou're running entirely local right now -- fast and private. "
            "Connecting a cloud model like Claude or Gemini gives you deeper analysis "
            "and the ability to chain models together for better results. "
            "Already have a Claude Pro or Gemini subscription? Just log in via Settings."
        )
    elif local_count == 0:
        lines.append(
            "\nTip: add local models via Ollama for fast, free, private responses "
            "on simple tasks. Saves your subscription quota for the hard stuff."
        )
    else:
        lines.append(
            f"\nYou've got {local_count} local + {cloud_count} cloud model(s). "
            "Great mix. Try chaining them -- type \"how do chains work\" to learn more."
        )

    return "\n".join(lines)


def _chain_explanation(models: list[str]) -> str:
    """Explain how model chaining works."""
    base = (
        "Chains let you pass work through multiple models in sequence. "
        "Each model sees the previous model's output and builds on it.\n\n"
        "For example:\n"
        '- "Llama, draft a blog post. Then have Claude edit it for tone."\n'
        '- "Mistral, analyze this data. Then Gemini, fact-check the conclusions."\n'
        '- "Summarize this with Llama, then have GPT turn it into an email."\n\n'
        "Why bother? Different models have different strengths. "
        "A local model can do the heavy first pass for free, "
        "then a cloud model polishes the result. Faster, cheaper, better."
    )

    if models and len(models) >= 2:
        names = []
        for m in models[:2]:
            p = _get_profile(m)
            n = p["display_name"]
            if n == "{model_id}":
                n = m.title()
            names.append(n)
        base += (
            f"\n\nTry it now: ask {names[0]} to do something, "
            f"then have {names[1]} refine or check the result."
        )
    elif models and len(models) == 1:
        base += (
            "\n\nYou'll need at least two models to chain. "
            "Add another model to get started!"
        )

    return base


def _generic_help(models: list[str]) -> str:
    """Generic help menu."""
    return (
        "Here are some things I can help with:\n\n"
        '- **"help me add Claude"** -- connect Claude (log in with your subscription or use an API key)\n'
        '- **"help me add Gemini"** -- connect Gemini (log in with your Google account or use an API key)\n'
        '- **"help me add GPT"** -- connect ChatGPT (log in with your subscription or use an API key)\n'
        '- **"what can you do"** -- see what your current models are good at\n'
        '- **"how do chains work"** -- learn about chaining models together\n\n'
        "Or just ask me anything -- I'm here to help."
    )


# ---------------------------------------------------------------------------
# First Chain Suggestion
# ---------------------------------------------------------------------------

def generate_first_chain_suggestion(models: list[str]) -> str:
    """Suggest a first chain after the user adds a new model.

    Best called right after a cloud model is successfully connected,
    to give the user an immediate "try this!" moment.

    Parameters
    ----------
    models : list[str]
        All currently available models (local + cloud).

    Returns
    -------
    str
        A friendly suggestion with a concrete example the user can try.
    """
    if len(models) < 2:
        return (
            "You've got one model ready. Connect another one and you'll unlock "
            "chaining -- where models work together for better results. "
            "Already paying for Claude or Gemini? Log in via Settings to add them instantly."
        )

    local = [m for m in models if _is_local(m)]
    cloud = [m for m in models if _is_cloud(m)]

    # Get display names
    def _name(model_id: str) -> str:
        p = _get_profile(model_id)
        n = p["display_name"]
        return n if n != "{model_id}" else model_id.title()

    if local and cloud:
        local_name = _name(local[0])
        cloud_name = _name(cloud[0])

        suggestions = [
            (
                f"Now that you have {cloud_name} + {local_name}, try this: "
                f'"Ask {local_name} to draft something, then have {cloud_name} refine it." '
                f"You'll see the difference chaining makes."
            ),
            (
                f"Nice -- {cloud_name} is on the team! Here's a quick chain to try: "
                f'"Analyze this code with {local_name}, then have {cloud_name} suggest improvements." '
                f"Local model does the fast pass, cloud model goes deep."
            ),
            (
                f"You've got {local_name} (fast, free) and {cloud_name} (deep, nuanced). "
                f"Try: \"{local_name}, summarize this article. Then {cloud_name}, "
                f'expand on the key insights." Best of both worlds.'
            ),
        ]
        return _pick(suggestions)

    elif len(cloud) >= 2:
        first_name = _name(cloud[0])
        second_name = _name(cloud[1])
        return (
            f"You've got {first_name} and {second_name} -- strong combo. "
            f"Try: \"{first_name}, analyze this problem. Then {second_name}, "
            f'critique the analysis." Two perspectives are better than one.'
        )

    elif len(local) >= 2:
        first_name = _name(local[0])
        second_name = _name(local[1])
        return (
            f"Two local models ready! Try: \"{first_name}, write a draft. "
            f"Then {second_name}, review it and suggest edits.\" "
            f"All running on your hardware, completely free."
        )

    # Fallback
    names = [_name(m) for m in models[:2]]
    return (
        f"You've got {names[0]} and {names[1]} ready. "
        f"Try asking them to work together: \"{names[0]}, start with X. "
        f'Then {names[1]}, build on that."'
    )


# ---------------------------------------------------------------------------
# Utility: get model profile info (for UI rendering)
# ---------------------------------------------------------------------------

def get_model_display_info(model_id: str) -> dict:
    """Return display metadata for a model (name, badge, color, tone).

    Useful for the UI to render model badges and color-code messages.
    """
    profile = _get_profile(model_id)
    name = profile["display_name"]
    if name == "{model_id}":
        name = model_id.title()
    return {
        "model_id": model_id,
        "display_name": name,
        "badge": profile.get("badge", "Model"),
        "color": profile.get("color", "#6b7280"),
        "tone": profile.get("tone", "neutral"),
        "strengths": profile.get("strengths", []),
    }
