"""LLMHosts uninstall -- clean removal of config, cache, and optionally models.

Two tiers:
  ``llmhosts uninstall``             -- removes config + data (keeps models)
  ``llmhosts uninstall --all``       -- removes everything including downloaded models

Flags:
  ``--keep-data``       -- preserve the data directory (~/.llmhosts)
  ``--remove-engine``   -- also remove the inference engine binary
  ``--yes / -y``        -- skip confirmation prompt

The inference engine binary is never touched unless ``--remove-engine`` is given.
"""

from __future__ import annotations

import logging
import os
import shutil
from pathlib import Path

logger = logging.getLogger(__name__)

# ---- Default paths ----
# Use pathlib for cross-platform path handling (Windows APPDATA, Unix XDG)
if os.name == "nt":
    _appdata = Path(os.environ.get("APPDATA", "")) if os.environ.get("APPDATA") else Path.home()
    _DEFAULT_DATA_DIR = str(_appdata / "llmhosts")
    _DEFAULT_CONFIG_DIR = str(_appdata / "llmhosts" / "config")
    _DEFAULT_MODELS_DIR = str(_appdata / "llmhosts" / "models")
else:
    _DEFAULT_DATA_DIR = str(Path.home() / ".llmhosts")
    _DEFAULT_CONFIG_DIR = str(Path.home() / ".config" / "llmhosts")
    _DEFAULT_MODELS_DIR = str(Path.home() / ".llmhosts" / "models")


def uninstall(
    data_dir: str = _DEFAULT_DATA_DIR,
    config_dir: str = _DEFAULT_CONFIG_DIR,
    models_dir: str = _DEFAULT_MODELS_DIR,
    confirm: bool = True,
    remove_all: bool = False,
    keep_data: bool = False,
) -> dict[str, bool]:
    """Remove LLMHosts data, config, and optionally models.

    Args:
        data_dir: Main data directory (``~/.llmhosts``).
        config_dir: XDG config directory (``~/.config/llmhosts``).
        models_dir: Downloaded models directory (``~/.llmhosts/models``).
        confirm: If *True*, prompt before deleting (unused when called programmatically).
        remove_all: If *True*, also remove downloaded models.
        keep_data: If *True*, preserve the data directory entirely.

    Returns:
        Dict mapping ``"data"``, ``"config"``, ``"models"`` to whether each was removed.
    """
    removed: dict[str, bool] = {}

    models_path = Path(models_dir)
    data_path = Path(data_dir)

    if keep_data:
        # Preserve the entire data directory (config, cache, models, everything)
        removed["data"] = False
        removed["models"] = False
    elif not remove_all and models_path.exists() and _is_subpath(models_path, data_path):
        # Models live inside data_dir -- preserve them while removing the rest
        import tempfile

        with tempfile.TemporaryDirectory() as tmpdir:
            tmp_models = Path(tmpdir) / "models_backup"
            shutil.copytree(str(models_path), str(tmp_models))

            if data_path.exists():
                shutil.rmtree(str(data_path))
                removed["data"] = True
                logger.info("Removed data: %s", data_dir)
            else:
                removed["data"] = False

            # Restore models
            models_path.parent.mkdir(parents=True, exist_ok=True)
            shutil.copytree(str(tmp_models), str(models_path))

        removed["models"] = False
    else:
        # Remove data directory
        if data_path.exists():
            shutil.rmtree(str(data_path))
            removed["data"] = True
            logger.info("Removed data: %s", data_dir)
        else:
            removed["data"] = False

        # Remove models (only with --all, and only if not already gone with data_dir)
        if remove_all and models_path.exists():
            shutil.rmtree(str(models_path))
            removed["models"] = True
            logger.info("Removed models: %s", models_dir)
        else:
            removed["models"] = False

    # Remove XDG config directory (~/.config/llmhosts)
    if not keep_data and os.path.exists(config_dir):
        shutil.rmtree(config_dir)
        removed["config"] = True
        logger.info("Removed config: %s", config_dir)
    else:
        removed["config"] = False

    return removed


def _is_subpath(child: Path, parent: Path) -> bool:
    """Check if *child* is inside *parent* (resolved)."""
    try:
        child.resolve().relative_to(parent.resolve())
        return True
    except ValueError:
        return False
