#!/usr/bin/env python3
"""
Set OneXPlayer Super X TDP limits through ryzenadj.
"""

from __future__ import annotations

import argparse
import json
import shutil
import subprocess
import sys
from pathlib import Path


MIN_WATTS = 3
MAX_WATTS = 120
MAX_BATTERY_WATTS = 80
LOCAL_RYZENADJ = Path("/usr/local/bin/ryzenadj")
AC_ONLINE_PATH = Path("/sys/class/power_supply/ACAD/online")
BATTERY_STATUS_PATH = Path("/sys/class/power_supply/BAT0/status")


def parse_args():
    parser = argparse.ArgumentParser(description="Set TDP through ryzenadj")
    parser.add_argument("watts", type=int)
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("--json", action="store_true")
    return parser.parse_args()


def ryzenadj_path() -> str:
    if LOCAL_RYZENADJ.exists():
        return str(LOCAL_RYZENADJ)
    found = shutil.which("ryzenadj")
    if found:
        return found
    raise FileNotFoundError("ryzenadj not found")


def emit(payload, as_json: bool):
    if as_json:
        print(json.dumps(payload, indent=2))
    else:
        print(payload)


def power_source() -> str:
    try:
        online = AC_ONLINE_PATH.read_text(encoding="utf-8").strip()
        if online == "1":
            return "ac"
        if online == "0":
            return "battery"
    except OSError:
        pass

    try:
        status = BATTERY_STATUS_PATH.read_text(encoding="utf-8").strip()
        if status == "Discharging":
            return "battery"
    except OSError:
        pass

    return "unknown"


def main():
    args = parse_args()
    if args.watts < MIN_WATTS or args.watts > MAX_WATTS:
        raise ValueError(f"watts must be in range {MIN_WATTS}-{MAX_WATTS}")
    source = power_source()
    if source == "battery" and args.watts > MAX_BATTERY_WATTS:
        raise ValueError(
            f"battery mode limit is {MAX_BATTERY_WATTS}W, requested {args.watts}W"
        )
    ryzenadj = ryzenadj_path()
    milliwatts = args.watts * 1000
    cmd = [
        ryzenadj,
        "--stapm-limit",
        str(milliwatts),
        "--fast-limit",
        str(milliwatts),
        "--slow-limit",
        str(milliwatts),
    ]
    payload = {
        "watts": args.watts,
        "milliwatts": milliwatts,
        "power_source": source,
        "backend": ryzenadj,
        "command": cmd,
    }
    if args.dry_run:
        payload["status"] = "dry-run"
        emit(payload, args.json)
        return
    subprocess.run(cmd, check=True)
    payload["status"] = "applied"
    emit(payload, args.json)


if __name__ == "__main__":
    try:
        main()
    except (FileNotFoundError, subprocess.CalledProcessError, ValueError) as exc:
        print(f"Error: {exc}", file=sys.stderr)
        sys.exit(1)
