"""Config Pack management commands — list, get, create, update, delete, toggle, backup, restore."""
from __future__ import annotations

from typing import Optional

import typer

from dattos_cli.client import ApiError
from dattos_cli.main import get_client, handle_api_error
from dattos_cli.output import is_tty, print_json
from dattos_cli.table import print_record, print_table


def _fmt_active(v) -> str:
    return "yes" if v else "\u2014"


CONFIG_PACKS_COLUMNS = [
    ("ID", "Id", None),
    ("Name", "Name", None),
    ("Description", "Description", None),
    ("Active", "IsActive", _fmt_active),
]

app = typer.Typer(help="Manage Dattos config packs.", no_args_is_help=True)


@app.command("list")
def config_packs_list(
    search: Optional[str] = typer.Option(None, "--search", "-s", help="Filter by name (partial match)."),
    page_size: int = typer.Option(50, "--page-size", help="Number of results per page."),
    no_cache: bool = typer.Option(False, "--no-cache", help="Bypass cache, fetch fresh data."),
    raw: bool = typer.Option(False, "--raw", help="Output raw JSON."),
):
    """List config packs in the organization."""
    client = get_client()
    params: dict = {"pageInfo.page": 0, "pageInfo.pageSize": page_size}
    if search:
        params["name"] = search
    try:
        resp = client.get("/api/ConfigPack", params=params, cache=not no_cache, cache_ttl=300)
        data = resp.get("Data", resp) if isinstance(resp, dict) else resp
        if raw or not is_tty():
            print_json(data)
        else:
            print_table(data, CONFIG_PACKS_COLUMNS, label="config packs")
    except ApiError as e:
        handle_api_error(e)


@app.command("get")
def config_packs_get(
    config_pack_id: int = typer.Argument(help="Config Pack ID."),
    raw: bool = typer.Option(False, "--raw", help="Output raw JSON."),
):
    """Get a config pack by ID."""
    client = get_client()
    try:
        data = client.get(f"/api/ConfigPack/{config_pack_id}")
        if raw or not is_tty():
            print_json(data)
        else:
            print_record(data)
    except ApiError as e:
        handle_api_error(e)


@app.command("create")
def config_packs_create(
    name: str = typer.Option(..., "--name", help="Config pack name."),
    description: str = typer.Option("", "--description", help="Config pack description."),
    raw: bool = typer.Option(False, "--raw", help="Output raw JSON."),
):
    """Create a new config pack."""
    client = get_client()
    payload = {
        "Id": 0,
        "Name": name,
        "Description": description,
        "IsActive": True,
    }
    try:
        data = client.post("/api/ConfigPack", json=payload)
        if raw or not is_tty():
            print_json(data)
        else:
            print_record(data)
    except ApiError as e:
        handle_api_error(e)


@app.command("update")
def config_packs_update(
    config_pack_id: int = typer.Argument(help="Config Pack ID to update."),
    name: Optional[str] = typer.Option(None, "--name", help="New config pack name."),
    description: Optional[str] = typer.Option(None, "--description", help="New description."),
    raw: bool = typer.Option(False, "--raw", help="Output raw JSON."),
):
    """Update a config pack's properties. Only provided fields are changed (read-modify-write)."""
    client = get_client()
    try:
        current = client.get(f"/api/ConfigPack/{config_pack_id}")
    except ApiError as e:
        handle_api_error(e)
        return
    if name is not None:
        current["Name"] = name
    if description is not None:
        current["Description"] = description
    try:
        data = client.put(f"/api/ConfigPack/{config_pack_id}", json=current)
        if raw or not is_tty():
            print_json(data)
        else:
            print_record(data)
    except ApiError as e:
        handle_api_error(e)


@app.command("delete")
def config_packs_delete(
    config_pack_id: int = typer.Argument(help="Config Pack ID to delete."),
    yes: bool = typer.Option(False, "--yes", "-y", help="Confirm deletion without prompt."),
):
    """Delete a config pack. Requires --yes to confirm (destructive, irreversible)."""
    if not yes:
        typer.echo("Error: deletion requires --yes flag to confirm.", err=True)
        raise typer.Exit(1)
    client = get_client()
    try:
        client.delete(f"/api/ConfigPack/{config_pack_id}")
        print_json({"status": "deleted", "configPackId": config_pack_id})
    except ApiError as e:
        handle_api_error(e)


@app.command("toggle")
def config_packs_toggle(
    config_pack_id: int = typer.Argument(help="Config Pack ID to toggle."),
    active: Optional[bool] = typer.Option(None, "--active/--inactive", help="Set active or inactive."),
):
    """Toggle a config pack's active status. Requires --active or --inactive flag."""
    if active is None:
        typer.echo("Error: must specify --active or --inactive.", err=True)
        raise typer.Exit(1)
    client = get_client()
    try:
        data = client.put("/api/ConfigPack/IsActive", json={"Id": config_pack_id, "IsActive": active})
        print_json(data)
    except ApiError as e:
        handle_api_error(e)


@app.command("backup")
def config_packs_backup(
    config_pack_id: int = typer.Argument(help="Config Pack ID to back up."),
):
    """Create a backup of a config pack."""
    client = get_client()
    try:
        data = client.post("/api/Backup/CreateConfigPackBackup", json={"ConfigPackId": config_pack_id})
        print_json(data)
    except ApiError as e:
        handle_api_error(e)


@app.command("restore")
def config_packs_restore(
    backup_id: int = typer.Argument(help="Backup ID to restore."),
):
    """Restore a config pack from a backup."""
    client = get_client()
    try:
        data = client.post("/api/ConfigurationRestore/Enqueue", json={"BackupId": backup_id})
        print_json(data)
    except ApiError as e:
        handle_api_error(e)
