"""MCP server that wraps the Atlassian CLI (acli) into generic tools."""

import asyncio
import json
import shlex
import shutil
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("acli-mcp-server")


def _acli_available() -> bool:
    return shutil.which("acli") is not None


async def _run_acli(command: str, timeout: int = 60) -> dict:
    """Execute an acli command and return structured output."""
    if not _acli_available():
        return {"error": "acli is not installed or not in PATH"}

    if not command.startswith("acli "):
        command = f"acli {command}"

    # Split into args and validate the binary is 'acli'
    try:
        args = shlex.split(command)
    except ValueError as e:
        return {"error": f"Invalid command syntax: {e}"}

    if not args or args[0] != "acli":
        return {"error": "Command must start with 'acli'"}

    # Block shell operators
    dangerous = {";", "&&", "||", "|", "`", "$(", "${", ">", "<", ">>"}
    for arg in args:
        for d in dangerous:
            if d in arg:
                return {"error": f"Blocked: shell operator '{d}' not allowed"}

    try:
        proc = await asyncio.create_subprocess_exec(
            *args,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await asyncio.wait_for(
            proc.communicate(), timeout=timeout
        )
    except asyncio.TimeoutError:
        return {"error": f"Command timed out after {timeout}s: {command}"}

    result: dict = {"command": command, "exit_code": proc.returncode}
    out = stdout.decode().strip() if stdout else ""
    err = stderr.decode().strip() if stderr else ""

    if proc.returncode != 0:
        result["error"] = err or "Command failed"
        if out:
            result["output"] = out
        return result

    # Try to parse as JSON for structured output
    try:
        result["output"] = json.loads(out)
    except (json.JSONDecodeError, ValueError):
        result["output"] = out

    if err:
        result["stderr"] = err

    return result


@mcp.tool()
async def call_acli(cli_command: str, timeout: int = 60) -> str:
    """Execute an Atlassian CLI (acli) command.

    The command must start with 'acli' and follow acli syntax.
    The --site flag is usually not needed — acli infers it from your auth session.

    Examples:
      - acli jira project list --limit 50
      - acli jira workitem search --jql "project = PROJ" --limit 20
      - acli jira workitem create --project PROJ --type Task --summary "Title"
      - acli jira workitem view PROJ-123
      - acli jira workitem transition --key PROJ-123 --status "Done"
      - acli jira board search
      - acli jira sprint list-workitems --sprint 1 --board 6
      - acli confluence space list
      - acli confluence page view --id 123456

    Args:
        cli_command: The full acli command to execute.
        timeout: Max seconds to wait for the command (default 60).
    """
    result = await _run_acli(cli_command, timeout)
    return json.dumps(result, indent=2, default=str)


@mcp.tool()
async def suggest_acli_commands(query: str) -> str:
    """Suggest acli commands based on a natural language description.

    Useful when you're unsure about the exact acli command syntax.

    Args:
        query: Natural language description of what you want to do.
    """
    suggestions = {
        "workitem": [
            "acli jira workitem search --jql 'project = PROJ' --limit 20",
            "acli jira workitem search --jql 'project = PROJ AND assignee = currentUser()' --limit 20",
            "acli jira workitem search --jql 'project = PROJ AND status = \"In Progress\"' --fields 'key,summary,status,priority,assignee'",
            "acli jira workitem search --filter 10001",
            "acli jira workitem view PROJ-123",
            "acli jira workitem view PROJ-123 --fields '*all'",
            "acli jira workitem create --project PROJ --type Task --summary 'Title'",
            "acli jira workitem create --project PROJ --type Task --summary 'Title' --assignee '@me'",
            "acli jira workitem create-bulk --from-csv issues.csv",
            "acli jira workitem create-bulk --from-json issues.json",
            "acli jira workitem edit --key PROJ-123 --summary 'New title'",
            "acli jira workitem edit --jql 'project = PROJ' --assignee 'user@atlassian.com' --yes",
            "acli jira workitem assign --key PROJ-123 --assignee '@me'",
            "acli jira workitem assign --key PROJ-123 --remove-assignee",
            "acli jira workitem transition --key PROJ-123 --status 'Done'",
            "acli jira workitem transition --jql 'project = PROJ AND status = \"To Do\"' --status 'In Progress'",
            "acli jira workitem clone --key PROJ-123 --to-project TEAM",
            "acli jira workitem delete --key PROJ-123 --yes",
            "acli jira workitem archive --key PROJ-123",
            "acli jira workitem unarchive --key PROJ-123",
            "acli jira workitem comment create --key PROJ-123 --body 'Comment text'",
            "acli jira workitem comment list --key PROJ-123",
            "acli jira workitem link create --out PROJ-123 --in PROJ-456 --type Blocks",
            "acli jira workitem link list --key PROJ-123",
            "acli jira workitem link type",
            "acli jira workitem attachment list --key PROJ-123",
            "acli jira workitem watcher list --key PROJ-123",
        ],
        "issue": [
            "# 'issue' = 'workitem' in acli. Use 'acli jira workitem' commands:",
            "acli jira workitem search --jql 'project = PROJ' --limit 20",
            "acli jira workitem view PROJ-123",
            "acli jira workitem create --project PROJ --type Bug --summary 'Title'",
        ],
        "search": [
            "acli jira workitem search --jql 'project = PROJ' --limit 50",
            "acli jira workitem search --jql 'assignee = currentUser() AND status != Done' --limit 20",
            "acli jira workitem search --jql 'project = PROJ AND type = Epic' --fields 'key,summary,status'",
            "acli jira workitem search --filter 10001",
            "acli jira board search --name 'Board Name'",
        ],
        "project": [
            "acli jira project list --limit 50",
            "acli jira project list --paginate",
            "acli jira project list --recent",
            "acli jira project view --key PROJ",
            "acli jira project view --key PROJ --json",
            "acli jira project create --from-project TEAM --key NEWTEAM --name 'New Project'",
            "acli jira project create --from-json project.json",
            "acli jira project update --project-key PROJ --name 'New Name'",
            "acli jira project delete --key PROJ",
            "acli jira project archive --key PROJ",
            "acli jira project restore --key PROJ",
        ],
        "board": [
            "acli jira board search",
            "acli jira board search --project PROJ",
            "acli jira board search --name 'Board Name' --type scrum",
            "acli jira board get --id 1",
            "acli jira board get --id 1 --json",
            "acli jira board create --name 'My Board' --type scrum --filter-id 10040 --location-type project --project PROJ",
            "acli jira board delete --id 1",
            "acli jira board list-sprints --id 1",
            "acli jira board list-sprints --id 1 --state active,closed",
            "acli jira board list-projects --id 1",
        ],
        "sprint": [
            "acli jira board list-sprints --id 1",
            "acli jira board list-sprints --id 1 --state active",
            "acli jira sprint view --id 1",
            "acli jira sprint view --id 1 --json",
            "acli jira sprint create --name 'Sprint 1' --board 5",
            "acli jira sprint create --name 'Sprint 2' --board 5 --start 2025-01-01 --end 2025-01-14 --goal 'Sprint goal'",
            "acli jira sprint update --id 37 --name 'Sprint 1 - Final'",
            "acli jira sprint update --id 37 --state closed",
            "acli jira sprint delete --id 37",
            "acli jira sprint list-workitems --sprint 1 --board 6",
            "acli jira sprint list-workitems --sprint 1 --board 6 --fields 'key,summary,status,assignee'",
        ],
        "page": [
            "acli confluence page view --id 123456",
            "acli confluence page view --id 123456 --json",
            "acli confluence page view --id 123456 --body-format storage",
        ],
        "space": [
            "acli confluence space list",
            "acli confluence space list --limit 50",
            "acli confluence space list --type personal",
            "acli confluence space list --keys 'KEY1,KEY2'",
            "acli confluence space view --id 123456",
            "acli confluence space view --id 123456 --include-all --json",
            "acli confluence space create --key SPACEKEY --name 'Space Name'",
            "acli confluence space create --key SPACEKEY --name 'Space Name' --description 'Description' --private",
            "acli confluence space update --key SPACEKEY --name 'New Name'",
            "acli confluence space archive --key SPACEKEY",
            "acli confluence space restore --key SPACEKEY",
        ],
        "auth": [
            "acli jira auth login --web",
            "acli jira auth status",
            "acli jira auth logout",
            "acli jira auth switch",
            "acli confluence auth login --web",
            "acli confluence auth status",
            "acli confluence auth logout",
            "acli confluence auth switch",
        ],
        "dashboard": [
            "acli jira dashboard search",
            "acli jira dashboard search --limit 10 --json",
            "acli jira dashboard search --name 'My Dashboard'",
            "acli jira dashboard search --owner user@atlassian.com",
        ],
        "filter": [
            "acli jira filter list --my",
            "acli jira filter list --favourite",
            "acli jira filter search",
            "acli jira filter search --name 'report' --limit 10",
            "acli jira filter search --owner user@atlassian.com",
            "acli jira filter get --id 12345",
            "acli jira filter get --id 12345 --json",
            "acli jira filter get --id 12345 --web",
            "acli jira filter update --id 10001 --name 'New Name' --jql 'project = PROJ'",
            "acli jira filter add-favourite --filter-id 12345",
            "acli jira filter change-owner --id 12345 --owner user@atlassian.com",
            "acli jira filter get-columns --key 12345",
            "acli jira filter reset-columns --id 12345",
        ],
        "field": [
            "acli jira field create --name 'Customer Name' --type 'com.atlassian.jira.plugin.system.customfieldtypes:textfield'",
            "acli jira field delete --id customfield_10001",
            "acli jira field cancel-delete --id customfield_10001",
        ],
        "blog": [
            "acli confluence blog list --space-id 12345",
            "acli confluence blog list --space-id 12345 --title 'Release Notes' --json",
            "acli confluence blog view --id 98765",
            "acli confluence blog view --id 98765 --body-format storage",
            "acli confluence blog create --space-id 12345 --title 'Post Title' --body '<p>Content</p>'",
            "acli confluence blog create --space-id 12345 --title 'Draft' --status draft --body '<p>WIP</p>'",
        ],
        "comment": [
            "acli jira workitem comment create --key PROJ-123 --body 'Comment text'",
            "acli jira workitem comment list --key PROJ-123",
            "acli jira workitem comment update --key PROJ-123 --id 10001 --body 'Updated text'",
            "acli jira workitem comment delete --key PROJ-123 --id 10001",
            "acli jira workitem comment visibility --role --project PROJ",
            "acli jira workitem comment visibility --group",
        ],
        "link": [
            "acli jira workitem link create --out PROJ-123 --in PROJ-456 --type Blocks",
            "acli jira workitem link list --key PROJ-123",
            "acli jira workitem link type",
            "acli jira workitem link delete --id 10001",
        ],
        "attachment": [
            "acli jira workitem attachment list --key PROJ-123",
            "acli jira workitem attachment delete --id 12345",
        ],
        "watcher": [
            "acli jira workitem watcher list --key PROJ-123",
            "acli jira workitem watcher remove --key PROJ-123 --user ACCOUNT_ID",
        ],
        "assign": [
            "acli jira workitem assign --key PROJ-123 --assignee '@me'",
            "acli jira workitem assign --key PROJ-123 --assignee 'user@atlassian.com'",
            "acli jira workitem assign --jql 'project = PROJ' --assignee 'default' --yes",
            "acli jira workitem assign --key PROJ-123 --remove-assignee",
        ],
        "clone": [
            "acli jira workitem clone --key PROJ-123 --to-project TEAM",
            "acli jira workitem clone --jql 'project = PROJ' --to-project TEAM --yes",
        ],
        "archive": [
            "acli jira workitem archive --key PROJ-123",
            "acli jira workitem archive --jql 'project = PROJ' --yes",
            "acli jira workitem unarchive --key PROJ-123",
            "acli confluence space archive --key SPACEKEY",
            "acli confluence space restore --key SPACEKEY",
        ],
        "delete": [
            "acli jira workitem delete --key PROJ-123 --yes",
            "acli jira workitem delete --jql 'project = PROJ' --yes",
            "acli jira board delete --id 1 --yes",
            "acli jira sprint delete --id 37 --yes",
            "acli jira field delete --id customfield_10001",
        ],
    }

    q = query.lower()
    matched = []
    for category, cmds in suggestions.items():
        if category in q or any(kw in q for kw in category):
            matched.extend(cmds)

    if not matched:
        matched = [f"# {cat}\n" + "\n".join(cmds) for cat, cmds in suggestions.items()]

    return json.dumps({"query": query, "suggestions": matched}, indent=2)


def main():
    mcp.run(transport="stdio")


if __name__ == "__main__":
    main()
