from typing import Optional, Union
from uuid import UUID

from radicli import Arg
from wasabi import msg

from ..cli import cli
from ..config import global_config_dir
from ..errors import CLIError
from ..messages import Messages
from ..query import resolve_action_id, resolve_project_id, resolve_task_id
from ..ui import print_mutation_result
from ..util import URL
from ._state import get_root_cfg, get_saved_settings


@cli.subcommand(
    "config",
    "reset",
    as_json=Arg("--json", help=Messages.as_json),
)
def reset(as_json: bool = False) -> None:
    """Reset all caching and configuration."""
    queue = list(global_config_dir().iterdir())
    for subpath in queue:
        if subpath.is_dir():
            queue.extend(list(subpath.iterdir()))
        else:
            msg.info(Messages.T021.format(subpath=subpath))
            subpath.unlink()
    print_mutation_result(
        {"status": "ok", "action": "reset"},
        "Configuration reset",
        as_json=as_json,
    )


@cli.subcommand(
    "config",
    "project",
    name_or_id=Arg(help=Messages.name_or_id.format(noun="project")),
    as_json=Arg("--json", help=Messages.as_json),
)
def project(name_or_id: Union[str, UUID], as_json: bool = False) -> UUID:
    """Set the default project."""
    root_cfg = get_root_cfg()
    project_id = resolve_project_id(name_or_id)
    settings = get_saved_settings()
    settings.update("project", project_id)
    settings.save(root_cfg.saved_settings_path)
    print_mutation_result(
        {"status": "ok", "project_id": str(project_id)},
        Messages.T019.format(noun="project", name=project_id),
        as_json=as_json,
    )
    return project_id


@cli.subcommand(
    "config",
    "task",
    name_or_id=Arg(help=Messages.name_or_id.format(noun="task")),
    project_id=Arg(help=Messages.project_id.format(noun="task")),
    cluster_id=Arg(help=Messages.cluster_id.format(noun="task")),
    as_json=Arg("--json", help=Messages.as_json),
)
def task(
    name_or_id: Union[str, UUID],
    cluster_id: Optional[UUID] = None,
    project_id: Optional[UUID] = None,
    as_json: bool = False,
) -> UUID:
    """Set the default task."""
    root_cfg = get_root_cfg()
    task_id = resolve_task_id(name_or_id, project_id=project_id, broker_id=cluster_id)
    settings = get_saved_settings()
    settings.update("task", task_id)
    settings.save(root_cfg.saved_settings_path)
    print_mutation_result(
        {"status": "ok", "task_id": str(task_id)},
        Messages.T019.format(noun="task", name=task_id),
        as_json=as_json,
    )
    return task_id


@cli.subcommand(
    "config",
    "action",
    name_or_id=Arg(help=Messages.name_or_id.format(noun="action")),
    project_id=Arg(help=Messages.project_id.format(noun="action")),
    cluster_id=Arg(help=Messages.cluster_id.format(noun="action")),
    as_json=Arg("--json", help=Messages.as_json),
)
def action(
    name_or_id: Union[str, UUID],
    cluster_id: Optional[UUID] = None,
    project_id: Optional[UUID] = None,
    as_json: bool = False,
) -> UUID:
    """Set the default action."""
    root_cfg = get_root_cfg()
    action_id = resolve_action_id(
        name_or_id, project_id=project_id, broker_id=cluster_id
    )
    settings = get_saved_settings()
    settings.update("action", action_id)
    settings.save(root_cfg.saved_settings_path)
    print_mutation_result(
        {"status": "ok", "action_id": str(action_id)},
        Messages.T019.format(noun="action", name=action_id),
        as_json=as_json,
    )
    return action_id


@cli.subcommand(
    "config",
    "set-cluster-host",
    host=Arg(help=Messages.cluster_host_config),
    as_json=Arg("--json", help=Messages.as_json),
)
def set_broker_host(host: str, as_json: bool = False) -> None:
    """Set the broker cluster host."""
    root_cfg = get_root_cfg()
    host_url = URL.parse(host)
    settings = get_saved_settings()
    settings.update("broker_host", str(host_url))
    settings.save(root_cfg.saved_settings_path)
    print_mutation_result(
        {"status": "ok", "cluster_host": str(host_url)},
        Messages.T019.format(noun="cluster host", name=host),
        as_json=as_json,
    )


@cli.subcommand(
    "config",
    "set-pam-host",
    host=Arg(help=Messages.pam_host_config),
    as_json=Arg("--json", help=Messages.as_json),
)
def set_pam_host(host: str, as_json: bool = False) -> None:
    """Set the PAM host."""
    root_cfg = get_root_cfg()
    host_url = URL.parse(host)
    settings = get_saved_settings()
    settings.update("pam_host", str(host_url))
    settings.save(root_cfg.saved_settings_path)
    print_mutation_result(
        {"status": "ok", "pam_host": str(host_url)},
        Messages.T019.format(noun="PAM host", name=host),
        as_json=as_json,
    )


@cli.subcommand(
    "config",
    "set-recipes-file",
    path=Arg(help="Path to a local recipes YAML file"),
    clear=Arg("--clear", help="Clear the recipes file setting"),
    as_json=Arg("--json", help=Messages.as_json),
)
def set_recipes_file(
    path: Optional[str] = None, clear: bool = False, as_json: bool = False
) -> None:
    """Set or clear a local recipes file for PAM-free recipe discovery."""
    root_cfg = get_root_cfg()
    settings = get_saved_settings()
    if clear:
        settings.update("recipes_file", None)
        settings.save(root_cfg.saved_settings_path)
        print_mutation_result(
            {"status": "ok", "recipes_file": None},
            "Cleared recipes file setting",
            as_json=as_json,
        )
        return
    if path is None:
        raise CLIError("Provide a path to a recipes file, or use --clear to remove it")
    from pathlib import Path as _Path

    resolved = str(_Path(path).resolve())
    settings.update("recipes_file", resolved)
    settings.save(root_cfg.saved_settings_path)
    print_mutation_result(
        {"status": "ok", "recipes_file": resolved},
        Messages.T019.format(noun="recipes file", name=resolved),
        as_json=as_json,
    )
