"""Base utilities for performance optimization — cross-platform."""
from __future__ import annotations

import ctypes
import json
import logging
import os
import platform
import subprocess
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Optional

logger = logging.getLogger(__name__)

IS_WINDOWS = platform.system() == "Windows"
IS_LINUX = platform.system() == "Linux"

# Rollback state directory
_STATE_DIR = Path.home() / ".mesh-optimizer" / "boost_state"


def is_admin() -> bool:
    """Check if running with elevated privileges (admin on Windows, root on Linux)."""
    if IS_WINDOWS:
        try:
            return ctypes.windll.shell32.IsUserAnAdmin() != 0
        except Exception:
            return False
    elif IS_LINUX:
        return os.geteuid() == 0
    return False


def require_admin(action: str) -> bool:
    """Log a warning if not admin/root. Returns True if elevated."""
    if not is_admin():
        logger.warning("Elevated privileges required for: %s — skipping", action)
        return False
    return True


# ── Sysfs/Sysctl Helpers (Linux) ─────────────────────────────────────────

def sysfs_read(path: str) -> Optional[str]:
    """Read a sysfs/procfs value. Returns None if not found."""
    try:
        return Path(path).read_text().strip()
    except (FileNotFoundError, PermissionError, OSError) as e:
        logger.debug("sysfs_read %s failed: %s", path, e)
        return None


def sysfs_write(path: str, value: str) -> bool:
    """Write a sysfs/procfs value. Requires root for most paths."""
    try:
        Path(path).write_text(str(value))
        return True
    except (PermissionError, OSError) as e:
        logger.error("sysfs_write %s failed: %s", path, e)
        return False


def sysctl_read(key: str) -> Optional[str]:
    """Read a sysctl value."""
    ok, output = run_cmd(["sysctl", "-n", key])
    return output if ok else None


def sysctl_write(key: str, value: str) -> bool:
    """Write a sysctl value. Requires root."""
    ok, _ = run_cmd(["sysctl", "-w", f"{key}={value}"])
    return ok


# ── Registry Helpers (Windows) ───────────────────────────────────────────

def reg_read(key_path: str, value_name: str) -> Optional[Any]:
    """Read a registry value. Returns None if not found."""
    if not IS_WINDOWS:
        return None
    try:
        import winreg
        hive, subkey = _parse_reg_path(key_path)
        with winreg.OpenKey(hive, subkey) as key:
            val, _ = winreg.QueryValueEx(key, value_name)
            return val
    except FileNotFoundError:
        return None
    except Exception as e:
        logger.debug("reg_read %s\\%s failed: %s", key_path, value_name, e)
        return None


def reg_write(key_path: str, value_name: str, value: Any,
              reg_type: int = None) -> bool:
    """Write a registry value. Creates the key if it doesn't exist."""
    if not IS_WINDOWS:
        return False
    try:
        import winreg
        if reg_type is None:
            reg_type = winreg.REG_DWORD if isinstance(value, int) else winreg.REG_SZ
        hive, subkey = _parse_reg_path(key_path)
        with winreg.CreateKeyEx(hive, subkey, 0, winreg.KEY_SET_VALUE) as key:
            winreg.SetValueEx(key, value_name, 0, reg_type, value)
        return True
    except Exception as e:
        logger.error("reg_write %s\\%s failed: %s", key_path, value_name, e)
        return False


def reg_delete(key_path: str, value_name: str) -> bool:
    """Delete a registry value."""
    if not IS_WINDOWS:
        return False
    try:
        import winreg
        hive, subkey = _parse_reg_path(key_path)
        with winreg.OpenKey(hive, subkey, 0, winreg.KEY_SET_VALUE) as key:
            winreg.DeleteValue(key, value_name)
        return True
    except FileNotFoundError:
        return True  # already gone
    except Exception as e:
        logger.debug("reg_delete %s\\%s failed: %s", key_path, value_name, e)
        return False


def _parse_reg_path(path: str):
    """Parse 'HKLM\\Software\\...' into (hive_constant, subkey_string)."""
    import winreg
    hives = {
        "HKLM": winreg.HKEY_LOCAL_MACHINE,
        "HKEY_LOCAL_MACHINE": winreg.HKEY_LOCAL_MACHINE,
        "HKCU": winreg.HKEY_CURRENT_USER,
        "HKEY_CURRENT_USER": winreg.HKEY_CURRENT_USER,
        "HKCR": winreg.HKEY_CLASSES_ROOT,
        "HKU": winreg.HKEY_USERS,
    }
    parts = path.split("\\", 1)
    hive_key = parts[0].upper()
    if hive_key not in hives:
        raise ValueError(f"Unknown registry hive: {parts[0]}")
    return hives[hive_key], parts[1] if len(parts) > 1 else ""


# ── Shell Helpers ────────────────────────────────────────────────────────

def run_powershell(command: str, timeout: int = 30) -> tuple[bool, str]:
    """Run a PowerShell command. Returns (success, output)."""
    try:
        result = subprocess.run(
            ["powershell", "-NoProfile", "-NonInteractive", "-Command", command],
            capture_output=True, text=True, timeout=timeout,
        )
        output = result.stdout.strip()
        if result.returncode != 0:
            err = result.stderr.strip()
            logger.debug("PowerShell failed: %s", err[:200])
            return False, err
        return True, output
    except subprocess.TimeoutExpired:
        logger.error("PowerShell timed out: %s", command[:80])
        return False, "timeout"
    except FileNotFoundError:
        logger.error("PowerShell not found")
        return False, "powershell not found"


def run_cmd(args: list[str], timeout: int = 30) -> tuple[bool, str]:
    """Run a command and return (success, output)."""
    try:
        result = subprocess.run(args, capture_output=True, text=True, timeout=timeout)
        return result.returncode == 0, result.stdout.strip()
    except Exception as e:
        return False, str(e)


# ── Rollback System ──────────────────────────────────────────────────────

class RollbackManager:
    """Save and restore original settings for safe optimization."""

    def __init__(self, module_name: str):
        self.module_name = module_name
        self._state_file = _STATE_DIR / f"{module_name}.json"
        self._originals: dict[str, Any] = {}
        self._load()

    def _load(self):
        if self._state_file.exists():
            try:
                self._originals = json.loads(self._state_file.read_text())
            except Exception:
                self._originals = {}

    def save_original(self, key: str, value: Any):
        """Save original value before modifying (only saves first time)."""
        if key not in self._originals:
            self._originals[key] = value
            self._persist()

    def get_original(self, key: str) -> Optional[Any]:
        """Get the saved original value."""
        return self._originals.get(key)

    def has_original(self, key: str) -> bool:
        return key in self._originals

    def clear(self, key: str = None):
        """Clear saved originals (after successful restore)."""
        if key:
            self._originals.pop(key, None)
        else:
            self._originals.clear()
        self._persist()

    def _persist(self):
        _STATE_DIR.mkdir(parents=True, exist_ok=True)
        self._state_file.write_text(json.dumps(self._originals, indent=2))

    @property
    def has_saved_state(self) -> bool:
        return bool(self._originals)


# ── Result Tracking ──────────────────────────────────────────────────────

class OptimizationResult:
    """Track what was applied and what failed."""

    def __init__(self, module: str):
        self.module = module
        self.applied: list[str] = []
        self.skipped: list[str] = []
        self.failed: list[str] = []
        self.timestamp = datetime.now(timezone.utc).isoformat()

    def ok(self, action: str):
        self.applied.append(action)
        logger.info("[%s] Applied: %s", self.module, action)

    def skip(self, action: str, reason: str = ""):
        self.skipped.append(f"{action}: {reason}" if reason else action)
        logger.debug("[%s] Skipped: %s %s", self.module, action, reason)

    def fail(self, action: str, error: str = ""):
        self.failed.append(f"{action}: {error}" if error else action)
        logger.warning("[%s] Failed: %s %s", self.module, action, error)

    def to_dict(self) -> dict:
        return {
            "module": self.module,
            "applied": self.applied,
            "skipped": self.skipped,
            "failed": self.failed,
            "timestamp": self.timestamp,
            "success_rate": f"{len(self.applied)}/{len(self.applied) + len(self.failed)}",
        }

    def __repr__(self):
        return (f"OptimizationResult({self.module}: "
                f"{len(self.applied)} applied, "
                f"{len(self.skipped)} skipped, "
                f"{len(self.failed)} failed)")
