"""MCP server exposing pygittools task boards to AI clients."""

from __future__ import annotations

import json
import os

from mcp.server import MCPServer
from pygittools.tasks import Task, _parse_dt, create_task
from pygittools.tasks_query import (
	BoardColumnView,
	BoardView,
	RepoLocation,
	TaskView,
	board_ref,
	discover_repo_path,
	get_board,
	get_board_tasks_grouped,
	get_task_view,
	list_boards,
	list_tasks,
	open_repository,
	resolve_repo_location,
)

from pygittools_mcp.exceptions import (
	BoardNotFoundError,
	InvalidTaskDueDateError,
	InvalidTaskPriorityError,
	InvalidTaskStatusError,
	TaskNotFoundError,
)
from pygittools_mcp.models import CreateTaskToolResult

mcp = MCPServer(
	"pygittools-tasks",
	instructions=(
		"Read task boards stored as Git annotated tags. "
		"Boards live under refs/tags/boards/, tasks under refs/tags/tasks/, "
		"and comments under refs/tags/comments/. "
		"Set PYGITTOOLS_REPO to a repository path, or PYGITWEB_PROJECTROOT plus a project name."
	),
)


def _repo_for_tool(project: str | None = None) -> RepoLocation:
	return resolve_repo_location(project=project)


@mcp.tool(title="List boards")
def list_boards_tool(project: str | None = None) -> list[BoardView]:
	"""List all task boards in the configured repository."""
	location = _repo_for_tool(project)
	repo = open_repository(location)
	return list_boards(repo)


@mcp.tool(title="List tasks")
def list_tasks_tool(
	board: str = "Tasks",
	project: str | None = None,
	include_comments: bool = True,
) -> list[TaskView]:
	"""List tasks on a board, optionally including comment bodies."""
	location = _repo_for_tool(project)
	repo = open_repository(location)
	try:
		return list_tasks(repo, board, include_comments=include_comments)
	except KeyError as exc:
		raise BoardNotFoundError(board) from exc


@mcp.tool(title="Get task")
def get_task_tool(task_ref: str, project: str | None = None) -> TaskView:
	"""Get one task by ref slug (task_123) or full ref (refs/tags/tasks/task_123)."""
	location = _repo_for_tool(project)
	repo = open_repository(location)
	try:
		return get_task_view(repo, task_ref, include_comments=True)
	except KeyError as exc:
		raise TaskNotFoundError(task_ref) from exc


@mcp.tool(title="Create task")
def create_task_tool(
	title: str,
	description: str,
	board: str = "Tasks",
	status: str = "TODO",
	priority: str = "LOW",
	assignee: str = "",
	due_date: str | None = None,
	tags: str | None = None,
	points: int | None = None,
	project: str | None = None,
) -> CreateTaskToolResult:
	"""Create a new task on a board."""
	location = _repo_for_tool(project)
	repo = open_repository(location)
	try:
		b = get_board(repo, board_ref(board))
		if b is None:
			raise BoardNotFoundError(board)
	except KeyError as e:
		raise BoardNotFoundError(board) from e

	try:
		s = Task.Status(status)
	except ValueError as e:
		raise InvalidTaskStatusError(status) from e

	try:
		p = Task.Priority(priority)
	except ValueError as e:
		raise InvalidTaskPriorityError(priority) from e

	try:
		d = _parse_dt(due_date)
	except ValueError as e:
		raise InvalidTaskDueDateError(due_date or "") from e

	try:
		result = create_task(
			repo=repo,
			board=b,
			title=title,
			description=description,
			status=s,
			priority=p,
			assignee=assignee,
			due_date=d,
			tags=tags or "",
			points=points,
		)
		return {"task_id": result["id"], "ref": result["ref"], "oid": str(result["oid"])}
	except Exception:
		raise


@mcp.tool(title="Board grouped by status")
def board_by_status_tool(
	board: str = "Tasks",
	project: str | None = None,
	include_comments: bool = True,
) -> list[BoardColumnView]:
	"""Return board tasks grouped into status columns (TODO, IN_PROGRESS, etc.)."""
	location = _repo_for_tool(project)
	repo = open_repository(location)
	try:
		return get_board_tasks_grouped(repo, board, include_comments=include_comments)
	except KeyError as exc:
		raise ValueError(str(exc)) from exc


@mcp.resource("board://{board_name}")
def board_resource(board_name: str) -> str:
	"""JSON snapshot of a board grouped by status."""
	location = resolve_repo_location()
	repo = open_repository(location)
	columns = get_board_tasks_grouped(repo, board_name, include_comments=True)
	return json.dumps(columns, indent=2)


@mcp.resource("task://{task_ref}")
def task_resource(task_ref: str) -> str:
	"""JSON snapshot of a single task with comments."""
	location = resolve_repo_location()
	repo = open_repository(location)
	task = get_task_view(repo, task_ref, include_comments=True)
	return json.dumps(task, indent=2)


def main() -> None:
	repo_env = os.environ.get("PYGITTOOLS_REPO", "").strip()
	if not repo_env:
		try:
			discovered = discover_repo_path()
		except FileNotFoundError:
			discovered = None
		if discovered is not None:
			os.environ["PYGITTOOLS_REPO"] = str(discovered)
	mcp.run(transport="stdio")


if __name__ == "__main__":
	main()