"""Meld MCP Server - Exposes Meld tools via Model Context Protocol."""

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import TextContent, Tool

from .api_client import MeldAPIClient
from .config import get_access_token, get_user_info

# Create server instance
mcp = Server("meld")

# API client instance
api = MeldAPIClient()


# ===========================================
# SESSION TOOLS
# ===========================================


@mcp.tool()
async def meld_hello() -> list[TextContent]:
    """Session start - returns user state and recommended action.

    Call this at the start of every session to:
    - Get personalized greeting
    - Know if check-in is recommended
    - Understand user's current state

    Returns:
        user_state: new_user, partial_onboard, onboarded, has_content, skipped_onboard
        recommended_action: checkin, ready
        greeting: Personalized greeting to use
        checkin_info: Whether check-in is suggested and why
    """
    # Check if logged in
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text=(
                    "Not logged in to Meld. "
                    "User needs to run 'meld login' in their terminal first."
                ),
            )
        ]

    result = await api.hello()

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    # Format response
    lines = [
        f"**User State:** {result.get('state')}",
        f"**Recommended Action:** {result.get('recommended_action')}",
        f"**Greeting:** {result.get('greeting')}",
        "",
        "**Content Counts:**",
        f"  - Projects: {result.get('content_counts', {}).get('projects', 0)}",
        f"  - Memories: {result.get('content_counts', {}).get('memories', 0)}",
        f"  - Profile slots: {result.get('content_counts', {}).get('slots', 0)}",
    ]

    checkin_info = result.get("checkin_info")
    if checkin_info and checkin_info.get("suggested"):
        lines.extend([
            "",
            "**Check-in Info:**",
            f"  - Suggested: Yes",
            f"  - Days since last: {checkin_info.get('days_since_last', 'never')}",
            f"  - Reason: {checkin_info.get('reason')}",
        ])

    return [TextContent(type="text", text="\n".join(lines))]


@mcp.tool()
async def meld_start_checkin() -> list[TextContent]:
    """Start a daily check-in session.

    Returns a session ID and list of questions to ask the user.
    Ask questions conversationally, one at a time.
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.start_checkin()

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    lines = [
        f"**Session ID:** {result.get('session_id')}",
        f"**Questions:** {result.get('question_count')}",
        "",
        "**Questions to ask:**",
    ]

    for q in result.get("questions", []):
        lines.append(f"  - [{q.get('id')}] {q.get('text')}")

    lines.extend([
        "",
        "Present questions conversationally, one at a time.",
        "After each response, call meld_checkin_respond() with the session_id, question_id, and response.",
    ])

    return [TextContent(type="text", text="\n".join(lines))]


@mcp.tool()
async def meld_checkin_respond(
    session_id: str,
    question_id: str,
    response: str,
) -> list[TextContent]:
    """Submit user's response to a check-in question.

    Args:
        session_id: The check-in session ID from meld_start_checkin
        question_id: The question ID (e.g., q1, q_project_xxx)
        response: The user's response text

    Use question_id="skip_rest" to end the check-in early.
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.checkin_respond(session_id, question_id, response)

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    lines = [f"**Acknowledged:** {result.get('acknowledged')}"]

    if result.get("is_complete"):
        lines.extend([
            "",
            "**Check-in complete!**",
            f"Summary: {result.get('summary', 'Thanks for the update!')}",
        ])
    elif result.get("next_question"):
        next_q = result["next_question"]
        lines.extend([
            "",
            f"**Next question:** [{next_q.get('id')}] {next_q.get('text')}",
        ])

    return [TextContent(type="text", text="\n".join(lines))]


# ===========================================
# MEMORY TOOLS
# ===========================================


@mcp.tool()
async def meld_remember(
    content: str,
    title: str | None = None,
    kind: str = "explicit",
) -> list[TextContent]:
    """Store a memory for the user.

    Args:
        content: The memory content to store
        title: Optional title/summary
        kind: Memory type (explicit, episodic, semantic, procedural)

    Use this when the user shares something worth remembering:
    - Personal info, preferences, decisions
    - Project updates, blockers, wins
    - Learnings, insights, patterns
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    # Check for duplicate first
    dup_check = await api.check_duplicate(content, kind)
    if dup_check.get("is_duplicate"):
        existing = dup_check.get("existing_memory", {})
        return [
            TextContent(
                type="text",
                text=(
                    f"Similar memory already exists (ID: {existing.get('id')}, "
                    f"similarity: {dup_check.get('similarity', 1.0):.0%}). "
                    "Not storing duplicate."
                ),
            )
        ]

    result = await api.store_memory(content, kind, title)

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    return [
        TextContent(
            type="text",
            text=f"Stored memory (ID: {result.get('id')}): {title or content[:50]}...",
        )
    ]


@mcp.tool()
async def meld_recall(query: str, limit: int = 5) -> list[TextContent]:
    """Search user's memories semantically.

    Args:
        query: What to search for (semantic search)
        limit: Max results (default 5, max 20)

    Returns relevant memories based on meaning, not just keywords.
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.recall(query, min(limit, 20))

    # api.recall() returns [] on error, so empty list means no results or error
    if not result:
        return [TextContent(type="text", text="No memories found matching that query.")]

    lines = [f"**Found {len(result)} memories:**", ""]
    for mem in result:
        title = mem.get("title") or mem.get("content", "")[:50]
        lines.append(f"- [{mem.get('id')}] {title}")
        lines.append(f"  {mem.get('content', '')[:100]}...")
        lines.append("")

    return [TextContent(type="text", text="\n".join(lines))]


# ===========================================
# PROFILE TOOLS
# ===========================================


@mcp.tool()
async def meld_get_profile() -> list[TextContent]:
    """Get user's profile with preferences, slots, and interests."""
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.get_profile()

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    lines = [
        "**Preferences:**",
        f"  - Depth: {result.get('preferences', {}).get('depth')}",
        f"  - Format: {result.get('preferences', {}).get('format')}",
        f"  - Autonomy: {result.get('preferences', {}).get('autonomy')}",
        "",
        "**Profile Slots:**",
    ]

    for key, value in result.get("slots", {}).items():
        lines.append(f"  - {key}: {value}")

    if result.get("interests"):
        lines.extend(["", "**Interests:**"])
        for interest in result.get("interests", []):
            lines.append(f"  - {interest.get('domain')} ({interest.get('priority')})")

    return [TextContent(type="text", text="\n".join(lines))]


@mcp.tool()
async def meld_set_slot(key: str, value: str, confidence: float = 0.9) -> list[TextContent]:
    """Set a profile slot (key-value pair about the user).

    Args:
        key: Slot name (e.g., name, company, role, current_focus)
        value: Slot value
        confidence: How confident (0-1, default 0.9)

    Common slots: name, company, role, location, timezone,
    primary_language, current_blockers, quarterly_goals
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.set_slot(key, value, confidence)

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    return [
        TextContent(
            type="text",
            text=f"Set slot '{key}' = '{value}' (superseded previous: {result.get('superseded_previous', False)})",
        )
    ]


# ===========================================
# PROJECT TOOLS
# ===========================================


@mcp.tool()
async def meld_list_projects(status: str | None = None) -> list[TextContent]:
    """List user's projects.

    Args:
        status: Filter by status (active, paused, completed) or None for all
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.list_projects(status)

    # api.list_projects() returns [] on error
    if not result:
        return [TextContent(type="text", text="No projects found.")]

    lines = [f"**Projects ({len(result)}):**", ""]
    for proj in result:
        proj_id = proj.get('id', '')
        lines.append(f"- [{proj_id[:8]}...] **{proj.get('name')}** ({proj.get('status')})")
        if proj.get("description"):
            lines.append(f"  {proj.get('description')[:100]}")
        lines.append("")

    return [TextContent(type="text", text="\n".join(lines))]


@mcp.tool()
async def meld_create_project(
    name: str,
    description: str | None = None,
    domains: list[str] | None = None,
    goals: list[str] | None = None,
) -> list[TextContent]:
    """Create a new project.

    Args:
        name: Project name
        description: What the project is about
        domains: Relevant domains/tags
        goals: Project goals
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.create_project(name, description, domains, goals)

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    return [
        TextContent(
            type="text",
            text=f"Created project '{name}' (ID: {result.get('id')})",
        )
    ]


@mcp.tool()
async def meld_update_project(
    project_id: str,
    name: str | None = None,
    description: str | None = None,
    status: str | None = None,
    domains: list[str] | None = None,
    goals: list[str] | None = None,
) -> list[TextContent]:
    """Update an existing project.

    Args:
        project_id: The project ID to update
        name: New project name (optional)
        description: New description (optional)
        status: New status: active, paused, completed (optional)
        domains: New domains/tags (optional)
        goals: New goals (optional)
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    # Build updates dict with only provided values
    updates = {}
    if name is not None:
        updates["name"] = name
    if description is not None:
        updates["description"] = description
    if status is not None:
        updates["status"] = status
    if domains is not None:
        updates["domains"] = domains
    if goals is not None:
        updates["goals"] = goals

    if not updates:
        return [TextContent(type="text", text="No updates provided.")]

    result = await api.update_project(project_id, **updates)

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    return [
        TextContent(
            type="text",
            text=f"Updated project '{result.get('name')}' (ID: {project_id})",
        )
    ]


@mcp.tool()
async def meld_add_interest(
    domain: str,
    specifics: list[str] | None = None,
    priority: str = "medium",
) -> list[TextContent]:
    """Add a domain of interest for the user.

    Args:
        domain: The interest domain (e.g., "machine learning", "real estate")
        specifics: Specific sub-topics within the domain (optional)
        priority: Importance level: low, medium, high (default: medium)

    Use this to track what topics the user is interested in.
    """
    if not get_access_token():
        return [
            TextContent(
                type="text",
                text="Not logged in to Meld. Run 'meld login' first.",
            )
        ]

    result = await api.add_interest(domain, specifics, priority)

    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]

    return [
        TextContent(
            type="text",
            text=f"Added interest: {domain} (priority: {priority})",
        )
    ]


# ===========================================
# SERVER MAIN
# ===========================================


def main():
    """Run the Meld MCP server."""
    import asyncio

    async def run():
        async with stdio_server() as (read_stream, write_stream):
            await mcp.run(
                read_stream,
                write_stream,
                mcp.create_initialization_options(),
            )

    asyncio.run(run())


if __name__ == "__main__":
    main()

