#!/usr/bin/env python3
"""rgb — command-line RGB control."""

from __future__ import annotations

import argparse
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))

import rgb_core as rc


def _targets(zone_arg: str) -> list[rc.Zone]:
    zones = rc.discover_zones()
    if not zones:
        raise SystemExit("no RGB zones found on this system")
    if zone_arg in ("all", "*"):
        return zones
    matches = [z for z in zones if z.id == zone_arg or z.name.lower() == zone_arg.lower()]
    if not matches:
        ids = ", ".join(z.id for z in zones)
        raise SystemExit(f"no zone matching {zone_arg!r}; known: {ids}, all")
    return matches


def cmd_list(_args: argparse.Namespace) -> int:
    zones = rc.discover_zones()
    if not zones:
        print("no RGB zones found", file=sys.stderr)
        return 1
    width = max(len(z.id) for z in zones)
    for z in zones:
        r, g, b = rc.read_color(z)
        bright = rc.read_brightness(z)
        print(
            f"{z.id:<{width}}  {z.name:<24}  "
            f"color=#{r:02x}{g:02x}{b:02x}  "
            f"brightness={bright}/{z.max_brightness}  "
            f"[{z.backend}]"
        )
    return 0


def cmd_set(args: argparse.Namespace) -> int:
    r, g, b = rc.parse_hex(args.color)
    for z in _targets(args.zone):
        rc.set_color(z, r, g, b)
        if args.verbose:
            print(f"{z.id}: #{r:02x}{g:02x}{b:02x}")
    return 0


def cmd_brightness(args: argparse.Namespace) -> int:
    for z in _targets(args.zone):
        level = args.level
        if level > z.max_brightness:
            level = z.max_brightness
        rc.set_brightness(z, level)
        if args.verbose:
            print(f"{z.id}: brightness={level}")
    return 0


def cmd_off(args: argparse.Namespace) -> int:
    zones = _targets(args.zone)
    for z in zones:
        rc.set_brightness(z, 0)
        if args.verbose:
            print(f"{z.id}: off")
    return 0


def cmd_on(args: argparse.Namespace) -> int:
    # Restore to the last non-zero brightness if we have it; otherwise max.
    state = rc.load_state()
    zones = _targets(args.zone)
    for z in zones:
        saved = state.get(z.id, {})
        pob = saved.get("pre_off_brightness")
        try:
            pob = int(pob) if pob is not None else None
        except (TypeError, ValueError):
            pob = None
        level = pob if pob is not None and 0 < pob <= z.max_brightness else z.max_brightness
        rc.set_brightness(z, level)
        if args.verbose:
            print(f"{z.id}: brightness={level}")
    return 0


def cmd_restore(args: argparse.Namespace) -> int:
    return rc.restore(verbose=args.verbose)


def build_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(prog="rgb", description="Control laptop RGB lighting.")
    p.add_argument("-v", "--verbose", action="store_true")
    sub = p.add_subparsers(dest="cmd", required=True)

    sub.add_parser("list", help="show zones and current state").set_defaults(func=cmd_list)

    s = sub.add_parser("set", help="set color of a zone (or 'all')")
    s.add_argument("zone", help="zone id, friendly name, or 'all'")
    s.add_argument("color", help="hex color, e.g. #ff00aa or f0a")
    s.set_defaults(func=cmd_set)

    s = sub.add_parser("brightness", help="set brightness level")
    s.add_argument("zone")
    s.add_argument("level", type=int, help="0..max (clamped)")
    s.set_defaults(func=cmd_brightness)

    o = sub.add_parser("off", help="set brightness 0; zone or 'all' (default: all)")
    o.add_argument("zone", nargs="?", default="all", help="zone id or 'all'")
    o.set_defaults(func=cmd_off)
    o = sub.add_parser("on", help="set max brightness; zone or 'all' (default: all)")
    o.add_argument("zone", nargs="?", default="all", help="zone id or 'all'")
    o.set_defaults(func=cmd_on)
    sub.add_parser(
        "restore",
        help="reapply the last saved color/brightness (used after resume / re-dock)",
    ).set_defaults(func=cmd_restore)
    return p


def main() -> None:
    args = build_parser().parse_args()
    try:
        sys.exit(args.func(args) or 0)
    except rc.RGBError as e:
        print(f"rgb: {e}", file=sys.stderr)
        sys.exit(2)
    except ValueError as e:
        print(f"rgb: {e}", file=sys.stderr)
        sys.exit(2)


if __name__ == "__main__":
    main()
