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

import argparse
import datetime
import logging
import os
import pathlib
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_ENV_CONF,
    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_gamescope_logging_env(log_dir: Optional[pathlib.Path] = None) -> bool:
    """Write MANGOHUD_CONFIG logging keys to ~/.config/environment.d/.

    On Bazzite/SteamOS, gamescope-session-plus exports MANGOHUD_CONFIGFILE
    pointing to a temp file managed by mangoapp.  Because MANGOHUD_CONFIGFILE
    takes precedence over MangoHud.conf and presets.conf, logging keys set
    there are never seen by game processes.

    The MANGOHUD_CONFIG env var is applied *on top* of MANGOHUD_CONFIGFILE, so
    writing it to ~/.config/environment.d/ injects logging keys into every game
    without disturbing the display behaviour that mangoapp controls.
    """
    effective_log_dir = log_dir or MANGOHUD_LOG_DIR
    effective_log_dir.mkdir(parents=True, exist_ok=True)

    logging_keys = {
        "output_folder": str(effective_log_dir),
        "toggle_logging": "Shift_L+F2",
        "log_duration": "0",
        "log_interval": "100",
        "log_versioning": "1",
    }
    config_value = ",".join(f"{k}={v}" for k, v in logging_keys.items())

    MANGOHUD_ENV_CONF.parent.mkdir(parents=True, exist_ok=True)
    content = (
        f"# MangoHud logging env -- written by {PROG_NAME} v{VERSION}\n"
        f"# Injects logging keys via MANGOHUD_CONFIG so they survive the\n"
        f"# gamescope-session MANGOHUD_CONFIGFILE temp-file override.\n"
        f"# Sourced by gamescope-session-plus from ~/.config/environment.d/\n"
        f"# Changes take effect on next gamescope session (re-login).\n"
        f'MANGOHUD_CONFIG="{config_value}"\n'
    )
    try:
        MANGOHUD_ENV_CONF.write_text(content, encoding="utf-8")
    except OSError as exc:
        log.error("Failed to write %s: %s", MANGOHUD_ENV_CONF, exc)
        return False

    print(f"  Gamescope logging env: {MANGOHUD_ENV_CONF}")
    print(f"    MANGOHUD_CONFIG set with logging keys -> {effective_log_dir}")
    print("    Re-login to gamescope session for changes to take effect.")
    return True


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}")

    if is_steamos():
        sync_gamescope_logging_env(log_dir=log_dir)

    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, which overrides MangoHud.conf and presets.conf.")
        print(f"      Logging keys written to: {MANGOHUD_ENV_CONF}")
        print("      Re-login to your gamescope session for logging to take effect.")
    return 0
