"""Click wrappers: project group — manage projects from CLI."""
from __future__ import annotations

import click

from proxym.cli._groups._shared import make_args as _make_args
from proxym.cli._client import print_json_if_yaml

PROJECTS_ENDPOINT = "/dashboard/projects"


def _list_projects(client):
    response = client.get(PROJECTS_ENDPOINT)
    data = response.json()
    return (data if isinstance(data, list) else data.get("projects", [])), data


def _resolve_project_id(client, project_ref):
    projects, _ = _list_projects(client)
    for project in projects:
        if project.get("id") == project_ref or project.get("name") == project_ref:
            return project.get("id")
    return None


def _build_project_update_payload(name, description, default_tool, environment_ids, tool_names, llm_names, user_ids):
    payload: dict[str, object] = {}
    if name is not None:
        payload["name"] = name
    if description is not None:
        payload["description"] = description
    if default_tool is not None:
        payload["default_tool"] = default_tool or None

    resolved_tool_names = list(tool_names)
    if default_tool:
        resolved_tool_names = list(dict.fromkeys([*resolved_tool_names, default_tool]))
    if resolved_tool_names:
        payload["tool_names"] = resolved_tool_names

    if environment_ids:
        payload["environment_ids"] = list(environment_ids)
    if llm_names:
        payload["llm_names"] = list(llm_names)
    if user_ids:
        payload["user_ids"] = list(user_ids)

    return payload


# ── Project group ─────────────────────────────────────────────

@click.group(name="project")
def project():
    """Manage projects (local, git, SSH, FTP)."""
    pass


@project.command(name="list")
@click.option("--type", "source_type", default=None, help="Filter by source type (local, git, ssh, ftp)")
@click.option("--status", default=None, help="Filter by status (active, archived, error)")
@click.pass_context
def project_list(ctx: click.Context, source_type, status):
    """List registered projects."""
    from proxym.cli._client import make_client, print_table
    args = _make_args(ctx)
    params = {}
    if source_type:
        params["source_type"] = source_type
    if status:
        params["status"] = status

    with make_client(args.proxy, args.key) as c:
        r = c.get(PROJECTS_ENDPOINT, params=params)
        data = r.json()

    projects = data if isinstance(data, list) else data.get("projects", [])
    if print_json_if_yaml(args, data):
        return

    print(f"\n  Projects ({len(projects)})\n")
    if not projects:
        print("  No projects found.\n")
        return

    print_table(
        projects,
        ["name", "source_type", "stack", "has_git", "default_tool", "ticket_count"],
        [20, 8, 25, 6, 14, 8],
    )
    print()


@project.command(name="add")
@click.argument("path_or_url")
@click.option("--git", is_flag=True, help="Treat argument as git URL")
@click.option("--ssh", is_flag=True, help="Treat argument as SSH (user@host:/path)")
@click.option("--name", default=None, help="Project name (auto-detected if not given)")
@click.option("--tool", default=None, help="Default tool (aider, claude-code, roo-code, ...)")
@click.pass_context
def project_add(ctx: click.Context, path_or_url, git, ssh, name, tool):
    """Add a project. Accepts local path, --git URL, or --ssh user@host:/path."""
    from proxym.cli._client import make_client
    args = _make_args(ctx)
    payload = {}
    if name:
        payload["name"] = name
    if tool:
        payload["default_tool"] = tool

    if git:
        payload["git_url"] = path_or_url
    elif ssh:
        # Parse user@host:/path
        if "@" in path_or_url and ":" in path_or_url:
            user_host, path = path_or_url.split(":", 1)
            user, host = user_host.split("@", 1)
            payload["ssh_host"] = host
            payload["ssh_path"] = path
            payload["ssh_user"] = user
        else:
            click.echo(f"  Invalid SSH format: {path_or_url} (expected user@host:/path)")
            return
    else:
        payload["path"] = path_or_url

    with make_client(args.proxy, args.key) as c:
        r = c.post(PROJECTS_ENDPOINT, json=payload)
        r.raise_for_status()
        data = r.json()

    stack = ", ".join(data.get("stack", []))
    click.echo(f"  \u2705 Added: {data['name']} ({data['source_type']}){' [' + stack + ']' if stack else ''}")


@project.command(name="scan")
@click.argument("directory", default="~/github")
@click.pass_context
def project_scan(ctx: click.Context, directory):
    """Scan a directory for projects and register them."""
    from proxym.cli._client import make_client
    args = _make_args(ctx)

    with make_client(args.proxy, args.key) as c:
        r = c.post(f"{PROJECTS_ENDPOINT}/scan", json={"directory": directory})
        r.raise_for_status()
        data = r.json()

    click.echo(f"  Scanned: {data['scanned']}")
    click.echo(f"  Added: {data['added']} project(s)")
    for p in data.get("projects", []):
        stack = ", ".join(p.get("stack", []))
        click.echo(f"    + {p['name']}{' [' + stack + ']' if stack else ''}")


@project.command(name="show")
@click.argument("project_id")
@click.pass_context
def project_show(ctx: click.Context, project_id):
    """Show project details."""
    from proxym.cli._client import make_client, print_json
    args = _make_args(ctx)

    with make_client(args.proxy, args.key) as c:
        r = c.get(f"{PROJECTS_ENDPOINT}/{project_id}")
        if r.status_code == 404:
            click.echo(f"  Project {project_id} not found.")
            return
        data = r.json()

    click.echo(f"\n  {data['id']}  {data['name']}")
    click.echo(f"  Type: {data['source_type']}  Status: {data['status']}")
    click.echo(f"  Path: {data['source_path']}")
    if data.get("local_path") and data["local_path"] != data["source_path"]:
        click.echo(f"  Local: {data['local_path']}")
    if data.get("stack"):
        click.echo(f"  Stack: {', '.join(data['stack'])}")
    if data.get("frameworks"):
        click.echo(f"  Frameworks: {', '.join(data['frameworks'])}")
    if data.get("default_tool"):
        click.echo(f"  Tool: {data['default_tool']}")
    click.echo(f"  Git: {'yes' if data.get('has_git') else 'no'}")
    click.echo(f"  Tickets: {data.get('ticket_count', 0)}")
    print()


@project.command(name="update")
@click.argument("project_ref")
@click.option("--name", default=None, help="New project name")
@click.option("--description", default=None, help="New project description")
@click.option("--tool", "default_tool", default=None, help="Primary tool")
@click.option("--env", "environment_ids", multiple=True, help="Attach an environment ID (repeatable)")
@click.option("--tool-name", "tool_names", multiple=True, help="Attach a tool name (repeatable)")
@click.option("--llm", "llm_names", multiple=True, help="Attach an LLM name (repeatable)")
@click.option("--user", "user_ids", multiple=True, help="Attach a user ID (repeatable)")
@click.pass_context
def project_update(ctx: click.Context, project_ref, name, description, default_tool, environment_ids, tool_names, llm_names, user_ids):
    """Update a project by id or name."""
    from proxym.cli._client import make_client
    args = _make_args(ctx)

    with make_client(args.proxy, args.key) as c:
        project_id = _resolve_project_id(c, project_ref)

        if not project_id:
            click.echo(f"  Project '{project_ref}' not found.")
            return

        payload = _build_project_update_payload(
            name=name,
            description=description,
            default_tool=default_tool,
            environment_ids=environment_ids,
            tool_names=tool_names,
            llm_names=llm_names,
            user_ids=user_ids,
        )

        if not payload:
            click.echo("  No project fields provided to update.")
            return

        r = c.put(f"{PROJECTS_ENDPOINT}/{project_id}", json=payload)
        if r.status_code == 404:
            click.echo(f"  Project '{project_ref}' not found.")
            return
        r.raise_for_status()
        data = r.json()

    if print_json_if_yaml(args, data):
        return

    click.echo(f"  \u2705 Updated: {data['name']} ({data['id']})")


@project.command(name="remove")
@click.argument("project_id")
@click.pass_context
def project_remove(ctx: click.Context, project_id):
    """Remove a project from the registry."""
    from proxym.cli._client import make_client
    args = _make_args(ctx)

    with make_client(args.proxy, args.key) as c:
        r = c.delete(f"{PROJECTS_ENDPOINT}/{project_id}")
        if r.status_code == 404:
            click.echo(f"  Project {project_id} not found.")
            return

    click.echo(f"  \u2705 Removed {project_id}")


@project.command(name="task")
@click.argument("project_name")
@click.argument("task_text")
@click.option("-t", "--tool", default=None, help="Tool to assign (aider, claude-code, ...)")
@click.option("--priority", default="medium", help="Priority: critical, high, medium, low")
@click.option("--type", "ticket_type", default="task", help="Type: task, bug, feature, refactor, test, docs")
@click.pass_context
def project_task(ctx: click.Context, project_name, task_text, tool, priority, ticket_type):
    """Create a ticket for a project (shortcut for 'ticket add --project')."""
    from proxym.cli._client import make_client
    args = _make_args(ctx)

    # Resolve project by name or id
    with make_client(args.proxy, args.key) as c:
        project_id = _resolve_project_id(c, project_name)

        if not project_id:
            click.echo(f"  Project '{project_name}' not found.")
            return

        payload = {
            "task": task_text,
            "project_id": project_id,
            "priority": priority,
            "type": ticket_type,
        }
        if tool:
            payload["tool"] = tool

        r = c.post("/dashboard/tickets", json=payload)
        r.raise_for_status()
        t = r.json()

    click.echo(f"  \u2705 {t['id']} {t.get('title', t.get('task', '')[:50])}")
