"""Configure command: generate / update MangoHud config files."""
from __future__ import annotations

import argparse
import datetime
import logging
import os
import pathlib
import shutil
import subprocess
import sys
import textwrap
from typing import Any, Dict, List, Optional

from .constants import (
    BOTTLENECK_KEYS,
    CONFIG_PRESETS,
    MANGOHUD_CONF_DIR,
    MANGOHUD_CONF_FILE,
    MANGOHUD_CONF_PATHS,
    MANGOHUD_LOG_DIR,
    PROG_NAME,
    VALVE_PRESETS,
    VERSION,
)
from .utils import is_steamos, log

# ── Internal helpers ───────────────────────────────────────────────────


def _find_active_mangohud_conf() -> Optional[pathlib.Path]:
    """Find the first existing MangoHud config in precedence order."""
    env_path = os.environ.get("MANGOHUD_CONFIGFILE")
    if env_path:
        p = pathlib.Path(env_path)
        if p.exists():
            return p
    for p in MANGOHUD_CONF_PATHS:
        if p.exists():
            return p
    return None


def _read_conf_keys(path: pathlib.Path) -> Dict[str, str]:
    """Parse an existing MangoHud.conf into key=value dict."""
    result: Dict[str, str] = {}
    for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
        line = line.strip()
        if not line or line.startswith("#"):
            continue
        if "=" in line:
            k, _, v = line.partition("=")
            result[k.strip()] = v.strip()
        else:
            result[line] = "1"
    return result


def _ensure_bottleneck_keys(conf_path: pathlib.Path) -> List[str]:
    """Check config has bottleneck + logging keys; return list of missing keys added."""
    from .constants import LOGGING_REQUIRED_KEYS

    existing = _read_conf_keys(conf_path)
    needed = {**BOTTLENECK_KEYS, **LOGGING_REQUIRED_KEYS}
    missing = {k: v for k, v in needed.items() if k not in existing}
    if not missing:
        return []
    addition = "\n# Added by mango-hud-profiler for bottleneck analysis + logging\n"
    addition += "\n".join(f"{k}={v}" for k, v in missing.items()) + "\n"
    with open(conf_path, "a", encoding="utf-8") as f:
        f.write(addition)
    return list(missing.keys())


def sync_config_to_preset(log_dir: Optional[pathlib.Path] = None) -> bool:
    """Write all 4 Valve presets (with logging) to ~/.config/MangoHud/presets.conf."""
    target_path = MANGOHUD_CONF_DIR / "presets.conf"
    target_path.parent.mkdir(parents=True, exist_ok=True)

    effective_log_dir = log_dir or MANGOHUD_LOG_DIR
    effective_log_dir.mkdir(parents=True, exist_ok=True)

    ts = datetime.datetime.now().isoformat()
    lines: List[str] = [
        f"# MangoHud presets.conf -- generated by {PROG_NAME} v{VERSION}",
        f"# Generated: {ts}",
        "#",
        "# Overrides Valve's default presets 1-4 to inject CSV logging.",
        "# The Steam Performance Overlay slider picks [preset N].",
        "# OSD appearance matches Valve's originals; logging runs silently.",
        "#   Toggle logging: Shift_L+F2  |  Logs: " + str(effective_log_dir),
        "",
    ]

    for num in sorted(VALVE_PRESETS):
        preset = VALVE_PRESETS[num]
        vals = dict(preset["values"])
        if log_dir:
            vals["output_folder"] = str(log_dir)
        lines.append(f"[preset {num}]")
        lines.append(f"# {preset['description']}")
        for k, v in vals.items():
            lines.append(f"{k}={v}")
        lines.append("")

    content = "\n".join(lines) + "\n"

    try:
        target_path.write_text(content, encoding="utf-8")
    except OSError as exc:
        log.error("Failed to write presets.conf: %s", exc)
        return False

    print(f"  Presets written: {target_path}")
    print(f"    Presets 1-4 now include CSV logging to {effective_log_dir}")
    print("    Toggle logging: Shift_L+F2 at any slider position.")
    for num in sorted(VALVE_PRESETS):
        desc = VALVE_PRESETS[num]["description"]
        print(f"      Preset {num}: {desc}")

    return True


# ── Subcommand handler ─────────────────────────────────────────────────


def cmd_configure(args: argparse.Namespace) -> int:
    pn = args.preset

    if args.game:
        game_conf = MANGOHUD_CONF_DIR / f"wine-{args.game}.conf"
        out = (
            pathlib.Path(args.output)
            if args.output != str(MANGOHUD_CONF_FILE)
            else game_conf
        )
    elif args.check:
        found = _find_active_mangohud_conf()
        if found:
            added = _ensure_bottleneck_keys(found)
            if added:
                print(f"  Updated: {found}")
                print(
                    f"    Added missing keys for bottleneck analysis: {', '.join(added)}"
                )
            else:
                print(f"  Config OK: {found}")
                print("    All bottleneck + logging keys already present.")
            return 0
        else:
            print("  No existing MangoHud config found. Creating new one...")
            out = MANGOHUD_CONF_FILE
    else:
        out = pathlib.Path(args.output)

    if pn not in CONFIG_PRESETS:
        log.error("Unknown preset '%s'. Available: %s", pn, ", ".join(CONFIG_PRESETS))
        return 1
    pr = CONFIG_PRESETS[pn]
    vals: Dict[str, Any] = dict(pr["values"])
    for pair in args.set or []:
        if "=" in pair:
            k, _, v = pair.partition("=")
            vals[k.strip()] = v.strip()
    if args.log_dir:
        vals["output_folder"] = str(args.log_dir)

    log_dir = pathlib.Path(vals.get("output_folder", str(MANGOHUD_LOG_DIR)))
    log_dir.mkdir(parents=True, exist_ok=True)

    hdr = textwrap.dedent(
        f"""\
        # MangoHud config -- {PROG_NAME} v{VERSION}
        # Preset: {pn} -- {pr['description']}
        # Generated: {datetime.datetime.now().isoformat()}
        # Docs: https://github.com/flightlessmango/MangoHud#mangohud_config
        # Toggle logging: Shift_L+F2 (start/stop CSV recording)
    """
    )
    txt = hdr + "\n" + "\n".join(f"{k}={v}" for k, v in vals.items()) + "\n"
    out.parent.mkdir(parents=True, exist_ok=True)
    if out.exists() and not args.force:
        log.warning("File exists: %s (use --force)", out)
        return 1

    sync_config_to_preset(log_dir=log_dir)

    out.write_text(txt, encoding="utf-8")
    scope = f"game '{args.game}' (wine-{args.game}.conf)" if args.game else "global"
    print(f"  Config written: {out}")
    print(f"    Preset: {pn} -- {pr['description']}")
    print(f"    Scope : {scope}")
    print(f"    Logs  : {log_dir}")
    print("    Toggle: Shift_L+F2 to start/stop logging")
    if args.game:
        print(f"    MangoHud auto-applies when running '{args.game}' via Proton/Wine.")
    print("\n    Config precedence (MangoHud checks in order):")
    print("      1. MANGOHUD_CONFIGFILE env var")
    if args.game:
        print(f"      2. ~/.config/MangoHud/wine-{args.game}.conf  <-- this file")
    print(f"      3. {MANGOHUD_CONF_FILE}")
    print("      4. ~/.var/app/com.valvesoftware.Steam/config/MangoHud/MangoHud.conf")
    if is_steamos():
        print("\n    Bazzite/SteamOS note:")
        print("      gamescope-session sets MANGOHUD_CONFIGFILE to a temp file managed")
        print("      by mangoapp, overriding MangoHud.conf and presets.conf for display.")
        print("      For per-game CSV logging, add to each game's Steam launch options:")
        print("        mangohud %command%")
        print("      Then press Shift_L+F2 in-game to start/stop recording.")
        print("      'mangohud-py organize' will auto-rename logs to the game name.")
    return 0


# ── auto-organize systemd units ────────────────────────────────────────

_SYSTEMD_USER_DIR = pathlib.Path.home() / ".config/systemd/user"
_SERVICE_NAME = "mangohud-organize.service"
_TIMER_NAME = "mangohud-organize.timer"


def _resolve_exec() -> str:
    """Return the best ExecStart path for the installed mangohud-py script."""
    p = shutil.which("mangohud-py")
    if p:
        return p
    return f"{sys.executable} -m mangohudpy"


def cmd_auto_organize(args: argparse.Namespace) -> int:
    """Install or remove the systemd user timer that runs 'organize' periodically."""
    if args.disable:
        return _disable_auto_organize()
    return _enable_auto_organize(args.interval)


def _enable_auto_organize(interval_min: int) -> int:
    exec_path = _resolve_exec()
    _SYSTEMD_USER_DIR.mkdir(parents=True, exist_ok=True)

    service = _SYSTEMD_USER_DIR / _SERVICE_NAME
    timer = _SYSTEMD_USER_DIR / _TIMER_NAME

    service.write_text(
        textwrap.dedent(f"""\
            [Unit]
            Description=MangoHud organize -- sort logs into per-game folders
            After=network.target

            [Service]
            Type=oneshot
            ExecStart={exec_path} organize
            StandardOutput=journal
            StandardError=journal
        """),
        encoding="utf-8",
    )

    timer.write_text(
        textwrap.dedent(f"""\
            [Unit]
            Description=Run MangoHud organize every {interval_min} minutes

            [Timer]
            OnBootSec=2min
            OnUnitActiveSec={interval_min}min
            Unit={_SERVICE_NAME}

            [Install]
            WantedBy=timers.target
        """),
        encoding="utf-8",
    )

    print(f"  Wrote: {service}")
    print(f"  Wrote: {timer}")

    try:
        subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
        subprocess.run(
            ["systemctl", "--user", "enable", "--now", _TIMER_NAME], check=True
        )
    except subprocess.CalledProcessError as exc:
        log.error("systemctl failed: %s", exc)
        return 1

    print(f"\n  Auto-organize enabled (every {interval_min} min, 2 min after login).")
    print(f"    Timer : {_TIMER_NAME}")
    print(f"    Exec  : {exec_path} organize")
    print("    Status: systemctl --user status mangohud-organize.timer")
    print("    Logs  : journalctl --user -u mangohud-organize.service")
    return 0


def _disable_auto_organize() -> int:
    try:
        subprocess.run(
            ["systemctl", "--user", "disable", "--now", _TIMER_NAME],
            check=True,
        )
    except subprocess.CalledProcessError as exc:
        log.error("systemctl failed: %s", exc)
        return 1

    for unit in (_SYSTEMD_USER_DIR / _SERVICE_NAME, _SYSTEMD_USER_DIR / _TIMER_NAME):
        if unit.exists():
            unit.unlink()
            print(f"  Removed: {unit}")

    subprocess.run(["systemctl", "--user", "daemon-reload"], check=False)
    print("  Auto-organize disabled and unit files removed.")
    return 0
