"""Servers CLI commands."""

from __future__ import annotations

import json

import typer

servers_app = typer.Typer(help="Manage servers")


def _format_memory_info(memory_info: str | None) -> tuple[str | None, str | None]:
    """Parse memory_info JSON and return formatted RAM and SWAP strings.

    Returns (ram_str, swap_str) where each is like "47% (7373/15619 MB)" or None.
    """
    if not memory_info:
        return None, None
    try:
        data = json.loads(memory_info)
        mem = data.get("mem", {})
        swap = data.get("swap", {})

        def fmt(info: dict) -> str | None:
            total = info.get("total")
            used = info.get("used")
            if total is None or used is None:
                return None
            if total == 0:
                return "0% (0/0 MB)"
            # Convert KB to MB
            total_mb = total // 1024
            used_mb = used // 1024
            pct = round(used / total * 100)
            return f"{pct}% ({used_mb}/{total_mb} MB)"

        return fmt(mem), fmt(swap)
    except (json.JSONDecodeError, TypeError, AttributeError):
        return None, None


def _format_disk_info(disk_info: str | None) -> str | None:
    """Parse disk_info JSON and return formatted disk usage string.

    Returns string like "64% (98093/153520 MB)" or None.
    """
    if not disk_info:
        return None
    try:
        data = json.loads(disk_info)
        total = data.get("size")
        used = data.get("used")
        if total is None or used is None:
            return None
        if total == 0:
            return "0% (0/0 MB)"
        # Convert KB to MB
        total_mb = total // 1024
        used_mb = used // 1024
        pct = round(used / total * 100)
        return f"{pct}% ({used_mb}/{total_mb} MB)"
    except (json.JSONDecodeError, TypeError, AttributeError):
        return None


@servers_app.command("list")
def servers_list(
    team: str = typer.Option(..., "--team", "-t", help="Team path"),
    output: str = typer.Option("table", "--output", "-o", help="Output format"),
) -> None:
    """List servers for a team."""
    from appliku.cli import get_client, render_output

    client = get_client()
    servers = client.servers.list(team)
    rows = [
        {"id": s.id, "name": s.name, "provider": s.provider, "region": s.region, "status": s.status}
        for s in servers
    ]
    render_output(rows, ["id", "name", "provider", "region", "status"], output, title="Servers")


@servers_app.command("get")
def servers_get(
    team: str = typer.Option(..., "--team", "-t", help="Team path"),
    server_id: int = typer.Argument(..., help="Server ID"),
    output: str = typer.Option("table", "--output", "-o", help="Output format"),
) -> None:
    """Get details of a server."""
    from appliku.cli import get_client, render_output

    client = get_client()
    s = client.servers.get(team, server_id)
    ram_str, swap_str = _format_memory_info(s.memory_info)
    disk_str = _format_disk_info(s.disk_info)
    rows = [
        {
            "id": s.id,
            "name": s.name,
            "provider": s.provider,
            "region": s.region,
            "status": s.status,
            "ip_address": s.ip_address,
            "uptime": s.uptime,
            "cpu_info": f"{s.cpu_info}%" if s.cpu_info is not None else None,
            "ram": ram_str,
            "swap": swap_str,
            "disk": disk_str,
            "requires_restart": s.requires_restart,
        }
    ]
    render_output(
        rows,
        [
            "id", "name", "provider", "region", "status", "ip_address",
            "uptime", "cpu_info", "ram", "swap", "disk", "requires_restart",
        ],
        output,
        title=f"Server: {s.name}",
    )


@servers_app.command("create-do")
def servers_create_do(
    team: str = typer.Option(..., "--team", "-t", help="Team path"),
    name: str = typer.Option(..., "--name", "-n", help="Server name"),
    region: str = typer.Option(..., "--region", "-r", help="DO region (e.g. nyc1)"),
    size: str = typer.Option(..., "--size", "-s", help="DO size (e.g. s-1vcpu-1gb)"),
    image: str | None = typer.Option(None, "--image", help="DO image slug"),
) -> None:
    """Create a DigitalOcean server."""
    from appliku.cli import get_client

    client = get_client()
    kwargs: dict[str, object] = {}
    if image:
        kwargs["image"] = image
    server = client.servers.create_digitalocean(team, name, region, size, **kwargs)
    typer.echo(f"Created server '{server.name}' (ID: {server.id})")


@servers_app.command("create-ec2")
def servers_create_ec2(
    team: str = typer.Option(..., "--team", "-t", help="Team path"),
    name: str = typer.Option(..., "--name", "-n", help="Server name"),
    region: str = typer.Option(..., "--region", "-r", help="AWS region (e.g. us-east-1)"),
    instance_type: str = typer.Option(
        ..., "--instance-type", "-i", help="EC2 instance type (e.g. t3.micro)"
    ),
    ami: str | None = typer.Option(None, "--ami", help="AMI ID"),
) -> None:
    """Create an EC2 server."""
    from appliku.cli import get_client

    client = get_client()
    kwargs: dict[str, object] = {}
    if ami:
        kwargs["ami"] = ami
    server = client.servers.create_ec2(team, name, region, instance_type, **kwargs)
    typer.echo(f"Created server '{server.name}' (ID: {server.id})")


@servers_app.command("create-custom")
def servers_create_custom(
    team: str = typer.Option(..., "--team", "-t", help="Team path"),
    name: str = typer.Option(..., "--name", "-n", help="Server name"),
    host: str = typer.Option(..., "--host", "-H", help="SSH hostname or IP"),
    ssh_port: int = typer.Option(22, "--port", help="SSH port"),
    ssh_username: str | None = typer.Option(None, "--username", "-u", help="SSH username"),
    ssh_key_name: str | None = typer.Option(None, "--key", "-k", help="SSH key name"),
) -> None:
    """Create a custom (SSH) server."""
    from appliku.cli import get_client

    client = get_client()
    kwargs: dict[str, object] = {"ssh_port": ssh_port}
    if ssh_username:
        kwargs["ssh_username"] = ssh_username
    if ssh_key_name:
        kwargs["ssh_key_name"] = ssh_key_name
    server = client.servers.create_custom(team, name, host, **kwargs)
    typer.echo(f"Created server '{server.name}' (ID: {server.id})")
