from __future__ import annotations

from typing import Any

from runtime import (
    MeetingPlan,
    MeetingState,
    PMDecision,
    AgentConfig,
    build_meeting_plan,
    build_pm_prompt,
    build_feedback_prompt,
    load_role_names,
)

DEFAULT_ROLE_ORDER = [
    "real_powell",
    "gstack_commercial",
    "gstack_technical",
    "gstack_ux",
]


def suggest_roles(topic: str, available: list[str] | None = None) -> list[str]:
    pool = available or load_role_names()
    selected = [name for name in DEFAULT_ROLE_ORDER if name in pool]
    if selected:
        return selected
    if len(pool) >= 3:
        return pool[:3]
    return pool


def suggest_roles_with_ai(topic: str, context: str, client: Any, available: list[str] | None = None) -> list[str]:
    pool = available or load_role_names()
    system = (
        "You are a meeting role selector. "
        "Given a topic and context, choose the best participants for a meeting. "
        "Return only a JSON object with fields: analysis, roles, rationale. "
        "roles must be a list of role names from the available pool."
    )
    user = (
        f"## Topic\n\n{topic}\n\n"
        f"## Context\n\n{context or 'None'}\n\n"
        f"## Available Roles\n\n{', '.join(pool)}"
    )
    raw = client.chat(system=system, messages=[{"role": "user", "content": user}])
    return parse_role_selection(raw, pool, topic)


def build_meeting_start_brief(topic: str, context: str = "", roles: list[str] | None = None, max_rounds: int = 10) -> dict[str, Any]:
    suggested = roles or suggest_roles(topic)
    return {
        "topic": topic,
        "context": context,
        "roles": suggested,
        "max_rounds": max_rounds,
        "notes": "Review or adjust before starting.",
    }


def build_meeting_start_brief_with_ai(topic: str, context: str, client: Any, max_rounds: int = 10) -> dict[str, Any]:
    suggested = suggest_roles_with_ai(topic=topic, context=context, client=client)
    return build_meeting_start_brief(topic=topic, context=context, roles=suggested, max_rounds=max_rounds)


def select_participants(plan: MeetingPlan) -> list[str]:
    if plan.roles:
        return plan.roles
    return suggest_roles(plan.topic)


def route_pm(plan: MeetingPlan, state: MeetingState, participants: dict[str, AgentConfig], client: Any) -> PMDecision:
    prompt = build_pm_prompt(plan, state, participants)
    system = (
        "You are the PM router for a multi-role meeting. "
        "Decide which role should speak next, or finish with a report. "
        "Output only valid JSON with fields analysis, next_action, target_agent, "
        "prompt_for_agent, final_report."
    )
    raw = client.chat(system=system, messages=[{"role": "user", "content": prompt}])
    return parse_pm_decision(raw)


def run_role(role_config: AgentConfig, prompt: str, client: Any) -> str:
    return client.chat(system=role_config.system_prompt, messages=[{"role": "user", "content": prompt}])


def build_feedback(plan: MeetingPlan, state: MeetingState) -> str:
    return build_feedback_prompt(plan, state)


def parse_role_selection(raw: str, available_roles: list[str], topic: str) -> list[str]:
    import json

    cleaned = raw.strip()
    if cleaned.startswith("```"):
        cleaned = cleaned.split("\n", 1)[1] if "\n" in cleaned else cleaned
        if cleaned.endswith("```"):
            cleaned = cleaned[:-3]
        cleaned = cleaned.strip()

    if not cleaned.startswith("{"):
        start = cleaned.find("{")
        end = cleaned.rfind("}")
        if start != -1 and end != -1 and end > start:
            cleaned = cleaned[start : end + 1]

    data = json.loads(cleaned)
    roles = data.get("roles", [])
    if not isinstance(roles, list):
        return suggest_roles(topic, available_roles)

    filtered = [role for role in roles if role in available_roles]
    return filtered or suggest_roles(topic, available_roles)


def parse_pm_decision(raw: str) -> PMDecision:
    import json
    from pydantic import ValidationError

    cleaned = raw.strip()
    if cleaned.startswith("```"):
        cleaned = cleaned.split("\n", 1)[1] if "\n" in cleaned else cleaned
        if cleaned.endswith("```"):
            cleaned = cleaned[:-3]
        cleaned = cleaned.strip()

    if not cleaned.startswith("{"):
        start = cleaned.find("{")
        end = cleaned.rfind("}")
        if start != -1 and end != -1 and end > start:
            cleaned = cleaned[start : end + 1]

    data = json.loads(cleaned)
    try:
        return PMDecision(**data)
    except ValidationError as exc:
        raise ValueError(str(exc)) from exc
