"""Thread handlers: post_turn, create_thread, fork_discussion,
update_project_toc, mark_discussion_decided, get_thread_comments.

Extended beyond #82's `{post_turn, create_thread, fork_discussion}`
spec to also host the orphan Discussion-side tools
(update_project_toc, mark_discussion_decided) and the general thread
reader (get_thread_comments). Keeping all Discussion-side tools
together matches the natural grouping of their github.discussions
dependencies and keeps issues.py focused on Issue-side workflow.
"""
from __future__ import annotations

from pathlib import Path

from mcp.types import TextContent

from ...context import ServerContext
from ...models import CreateThreadResult, ForkResult, PostTurnResult
from ...utils import check_overwrite_size
# Late binding — see helpers.py docstring.
from active_claude_github_mcp import server as _s
from ..helpers import fetch_project_toc_body, ok


async def post_turn(
    ctx: ServerContext,
    thread_id: str,
    thread_type: str,
    speaker: str,
    body: str,
    proj_dir: Path,
) -> list[TextContent]:
    prefix = "**Claude:**" if speaker == "claude" else "**User:**"
    formatted = f"{prefix} {body}"

    if thread_type == "discussion":
        result = _s.add_discussion_comment(ctx.github_token, thread_id, formatted)
    else:
        result = _s.add_issue_comment(ctx.github_token, thread_id, formatted)

    ctx.activity.turns_posted += 1
    ctx.activity.turns_by_thread[thread_id] = (
        ctx.activity.turns_by_thread.get(thread_id, 0) + 1
    )

    toc_body = None
    if thread_id == ctx.config.project_discussion_id:
        toc_body = fetch_project_toc_body(
            ctx.github_token, ctx.config.project_discussion_id
        )

    return ok(
        PostTurnResult(
            comment_id=result["id"],
            comment_url=result["url"],
            project_toc_body=toc_body,
        ).model_dump()
    )


async def create_thread(
    ctx: ServerContext,
    thread_type: str,
    category_or_label: str,
    title: str,
    opening_body: str,
    discussion_origin_id: str,
    owner: str,
    repo: str,
) -> list[TextContent]:
    repo_id = _s.get_repo_node_id(ctx.github_token, owner, repo)

    if thread_type == "discussion":
        cat_map = {
            "Architecture": ctx.config.discussion_categories.Architecture.id,
            "UX / UI": ctx.config.discussion_categories.UX_UI.id,
            "Ideas": ctx.config.discussion_categories.Ideas.id,
        }
        category_id = cat_map.get(category_or_label)
        if not category_id:
            raise ValueError(
                f"Unknown Discussion category: {category_or_label!r}. "
                "Must be one of: Architecture, UX / UI, Ideas"
            )
        result = _s.create_discussion(
            ctx.github_token, repo_id, category_id, title, opening_body
        )
        ctx.activity.discussions_created += 1
        return ok(
            CreateThreadResult(
                thread_id=result["id"],
                thread_number=result["number"],
                thread_url=result["url"],
                type="discussion",
                project_toc_body=fetch_project_toc_body(
                    ctx.github_token, ctx.config.project_discussion_id
                ),
            ).model_dump()
        )

    label_id = _s.get_label_id(ctx.github_token, owner, repo, category_or_label)
    result = _s.create_issue(
        ctx.github_token, repo_id, title, opening_body, [label_id]
    )
    _s.add_item_to_project(
        ctx.github_token, ctx.config.project_board.id, result["id"]
    )
    ctx.activity.issues_created += 1
    return ok(
        CreateThreadResult(
            thread_id=result["id"],
            thread_number=result["number"],
            thread_url=result["url"],
            type="issue",
            project_toc_body=fetch_project_toc_body(
                ctx.github_token, ctx.config.project_discussion_id
            ),
        ).model_dump()
    )


async def fork_discussion(
    ctx: ServerContext,
    arguments: dict,
    owner: str,
    repo: str,
) -> list[TextContent]:
    """Execute fork sequence. Not atomic — GitHub has no transaction API.
    Partial failures are reported so the caller can retry."""
    original_id = arguments["original_id"]
    fork_point_comment_id = arguments["fork_point_comment_id"]  # noqa: F841 — reserved
    new_title = arguments["new_title"]
    category_name = arguments["category_name"]
    summary = arguments["summary"]
    original_url = arguments["original_discussion_url"]
    fork_point_url = arguments["fork_point_url"]

    cat_map = {
        "Architecture": ctx.config.discussion_categories.Architecture.id,
        "UX / UI": ctx.config.discussion_categories.UX_UI.id,
        "Ideas": ctx.config.discussion_categories.Ideas.id,
    }
    category_id = cat_map.get(category_name)
    if not category_id:
        raise ValueError(f"Unknown category: {category_name!r}")

    repo_id = _s.get_repo_node_id(ctx.github_token, owner, repo)

    new_opening = (
        f"## Forked from: [{original_url}]({original_url})\n"
        f"Fork point: [{fork_point_url}]({fork_point_url})\n\n"
        f"## Context Summary\n{summary}\n\n"
        f"---\n*Conversation continues from here.*"
    )
    new_disc = _s.create_discussion(
        ctx.github_token, repo_id, category_id, new_title, new_opening
    )
    new_disc_id = new_disc["id"]
    new_disc_url = new_disc["url"]

    _s.get_discussion_comments(ctx.github_token, original_id, last_n=1)
    fork_notice = (
        f"> ⚠️ This thread was partially forked.\n"
        f"> Content from [{fork_point_url}]({fork_point_url}) onward "
        f"continues in: **[{new_title}]({new_disc_url})**\n\n"
    )
    original_updated = False
    try:
        _s.add_discussion_comment(ctx.github_token, original_id, fork_notice)
        original_updated = True
    except _s.GitHubError:
        original_updated = False

    fork_comment_body = (
        f"---\n"
        f"*Thread continues in [{new_title}]({new_disc_url}) from this point.*\n"
        f"---"
    )
    fork_comment = _s.add_discussion_comment(
        ctx.github_token, original_id, fork_comment_body
    )

    ctx.activity.forks_executed += 1
    return ok(
        ForkResult(
            new_discussion_id=new_disc_id,
            new_discussion_url=new_disc_url,
            original_updated=original_updated,
            fork_comment_id=fork_comment["id"],
            project_toc_body=fetch_project_toc_body(
                ctx.github_token, ctx.config.project_discussion_id
            ),
        ).model_dump()
    )


async def update_project_toc(
    ctx: ServerContext,
    new_body: str,
    force: bool,
) -> list[TextContent]:
    current_body = _s.get_discussion_body(
        ctx.github_token, ctx.config.project_discussion_id
    )
    check_overwrite_size(current_body, new_body, force)
    _s.update_discussion_body(
        ctx.github_token, ctx.config.project_discussion_id, new_body
    )
    return ok("Project Discussion TOC updated.")


async def mark_decided(
    ctx: ServerContext,
    discussion_id: str,
    decision_comment_id: str,
    category_name: str,
) -> list[TextContent]:
    cat_map = {
        "Architecture": ctx.config.discussion_categories.Architecture,
        "UX / UI": ctx.config.discussion_categories.UX_UI,
        "Ideas": ctx.config.discussion_categories.Ideas,
    }
    category = cat_map.get(category_name)
    answer_marked = False

    if category and category.is_answerable:
        try:
            _s.mark_discussion_answer(ctx.github_token, decision_comment_id)
            answer_marked = True
        except _s.GitHubError:
            answer_marked = False

    ctx.activity.discussions_decided += 1
    return ok(
        {
            "answer_marked": answer_marked,
            "message": (
                "Discussion marked as decided."
                if answer_marked
                else "Decision comment posted. Category does not support Answer marking."
            ),
            "project_toc_body": fetch_project_toc_body(
                ctx.github_token, ctx.config.project_discussion_id
            ),
        }
    )


async def get_thread_comments(
    ctx: ServerContext,
    thread_id: str,
    thread_type: str,
    limit: int,
) -> list[TextContent]:
    comments = _s.list_thread_comments(
        ctx.github_token, thread_id, thread_type, limit=limit
    )
    return ok({"comments": comments})
