"""Persistent configuration and session management for auto-yes.

Config lives at ``~/.config/auto-yes/config.json`` on Unix or
``%APPDATA%/auto-yes/config.json`` on Windows.

Session files live under ``sessions/`` in the same directory.  Each running
auto-yes process registers a ``<pid>.json`` file at startup and removes it
on exit.  A ``<pid>.pause`` file signals the process to suspend detection.
"""

import contextlib
import json
import os
import time

_DIR_NAME = "auto-yes"
_FILE_NAME = "config.json"

_DEFAULTS = {
    "custom_patterns": [],
    "response": "y",
    "cooldown": 0.5,
    "verbose": False,
}


def _config_dir():
    if os.name == "nt":
        base = os.environ.get("APPDATA", os.path.expanduser("~"))
    else:
        base = os.environ.get(
            "XDG_CONFIG_HOME",
            os.path.join(os.path.expanduser("~"), ".config"),
        )
    return os.path.join(base, _DIR_NAME)


def _config_path():
    return os.path.join(_config_dir(), _FILE_NAME)


# ------------------------------------------------------------------
# public helpers
# ------------------------------------------------------------------


def load():
    """Load config from disk, falling back to defaults for missing keys."""
    path = _config_path()
    if not os.path.isfile(path):
        return dict(_DEFAULTS)

    with open(path, encoding="utf-8") as fh:
        data = json.load(fh)

    merged = dict(_DEFAULTS)
    merged.update(data)
    return merged


def save(cfg):
    """Persist *cfg* dict to the config file."""
    dir_path = _config_dir()
    os.makedirs(dir_path, exist_ok=True)

    with open(_config_path(), "w", encoding="utf-8") as fh:
        json.dump(cfg, fh, indent=2, ensure_ascii=False)
        fh.write("\n")


def add_pattern(pattern):
    """Append *pattern* to the custom-patterns list (deduplicated)."""
    cfg = load()
    if pattern not in cfg["custom_patterns"]:
        cfg["custom_patterns"].append(pattern)
        save(cfg)
    return cfg


def remove_pattern(pattern):
    """Remove *pattern* from the custom-patterns list if present."""
    cfg = load()
    if pattern in cfg["custom_patterns"]:
        cfg["custom_patterns"].remove(pattern)
        save(cfg)
    return cfg


def config_path():
    """Return the resolved path to the config file (for display)."""
    return _config_path()


# ------------------------------------------------------------------
# session management
# ------------------------------------------------------------------


def _sessions_dir():
    return os.path.join(_config_dir(), "sessions")


def register_session(pid, profile, command):
    """Write a session file so other terminals can discover this process."""
    d = _sessions_dir()
    os.makedirs(d, exist_ok=True)
    info = {
        "profile": profile,
        "command": command,
        "started": time.time(),
    }
    path = os.path.join(d, f"{pid}.json")
    with open(path, "w", encoding="utf-8") as fh:
        json.dump(info, fh)


def unregister_session(pid):
    """Remove session and pause files for *pid*."""
    d = _sessions_dir()
    for suffix in (".json", ".pause"):
        with contextlib.suppress(FileNotFoundError):
            os.remove(os.path.join(d, f"{pid}{suffix}"))


def is_paused(pid):
    """Return True if a pause file exists for *pid*."""
    return os.path.exists(os.path.join(_sessions_dir(), f"{pid}.pause"))


def set_paused(pid, paused):
    """Create or remove the pause file for *pid*."""
    d = _sessions_dir()
    os.makedirs(d, exist_ok=True)
    path = os.path.join(d, f"{pid}.pause")
    if paused:
        open(path, "w").close()
    else:
        with contextlib.suppress(FileNotFoundError):
            os.remove(path)


def _pid_alive(pid):
    """Check whether *pid* is a running process."""
    try:
        os.kill(pid, 0)
        return True
    except (ProcessLookupError, PermissionError):
        return False


def list_sessions():
    """Return a list of ``(pid, info_dict, paused)`` for live sessions.

    Stale entries (dead PIDs) are cleaned up automatically.
    """
    d = _sessions_dir()
    if not os.path.isdir(d):
        return []

    results = []
    for name in os.listdir(d):
        if not name.endswith(".json"):
            continue
        pid_str = name[:-5]
        if not pid_str.isdigit():
            continue
        pid = int(pid_str)

        if not _pid_alive(pid):
            unregister_session(pid)
            continue

        path = os.path.join(d, name)
        try:
            with open(path, encoding="utf-8") as fh:
                info = json.load(fh)
        except (OSError, json.JSONDecodeError):
            continue

        paused = is_paused(pid)
        results.append((pid, info, paused))

    results.sort(key=lambda x: x[1].get("started", 0))
    return results
