#!/usr/bin/env python3

import subprocess
import shutil
from argparse import ArgumentParser
from pathlib import Path

BASE_PKGS = [
    "clang",  # C/C++ development
    "scripts",  # scripts & snippets
    "stow",  # --target=~
]

# for TUI only setups
# e.g. servers that are accessed via SSH only
TUI_PKGS = [
    *BASE_PKGS,
    "fastfetch",  # sys info,
    "helix",  # editor
    "nvim",  # editor
    "shell",  # fish & .bash_profile & shell prompt
    "yazi",  # terminal file manager
]

# for all WMs and DEs
GUI_BASE_PKGS = [
    *TUI_PKGS,
    "cava",
    "kitty",  # terminal emulator
    "ghostty",  # alternative terminal emulator
    "misc",  # miscellaneous GUI configs (e.g. *-flags)
    "mpd",  # music player daemon
    # "mpv",          # media player
    "wallpaper",  # wallpapers & manager
    "kvantum",  # qt theming
    "nwg-look",  # gtk theming
    "wezterm",  # alternative terminal emulator
]

# for Hyprland setup
# HYPRLAND_PKGS = [
#     *GUI_BASE_PKGS,
#     "eww",  # widgets
#     "hypr",  # hypr family
#     "hyprland",  # wm config
#     "mako",  # notifications
#     "rofi",  # application launcher
#     "waybar",  # status bar
#     "wlogout",  # logout menu
# ]

# for Niri setup
NIRI_PKGS = [
    *GUI_BASE_PKGS,
    "hypr",  # for hyprlock & hypridle
    "niri",  # wm config
    "quickshell",  # widgets & status bar & notifications & ...
    "rofi",  # application launcher
    "wlogout",  # logout menu
]

PKGS = {
    "base": BASE_PKGS,
    "tui": TUI_PKGS,
    "gui": GUI_BASE_PKGS,
    # "hyprland": HYPRLAND_PKGS,
    "niri": NIRI_PKGS,
}

SESSION_NAME = {
    "hyprland": "Hyprland",
    "niri": "niri",
    "default": "default",
}


PKGS_PATH = Path(__file__).resolve().parent.resolve() / "config"
DEST_PATH = Path.home().expanduser()


def _log(level: str, message: str):
    color = (
        "\033[92m" if level == "INFO" else "\033[91m" if level == "ERROR" else "\033[0m"
    )
    reset = "\033[0m"
    print(f"{color}[{level}] {message}{reset}")


def check_deps() -> bool:
    required_deps = ["stow"]
    for dep in required_deps:
        if not shutil.which(dep):
            _log("ERROR", f"Required dependency '{dep}' is not installed.")
            return False
    return True


def stow(pkg: str):
    subprocess.run(
        ["stow", "-v", "-d", str(PKGS_PATH), "-t", str(DEST_PATH), pkg], check=True
    )


def unstow(pkg: str):
    subprocess.run(
        ["stow", "-v", "-d", str(PKGS_PATH), "-t", str(DEST_PATH), "-D", pkg], check=True,
    )


def switch(session: str):
    subprocess.run(
        [str(Path("~/.local/scripts/config-switch").expanduser()), session], check=True
    )


def main():
    if not check_deps():
        exit(1)

    parser = ArgumentParser(
        description="Stow configuration packages in this repository."
    )
    parser.add_argument(
        "package", choices=PKGS.keys(), help="The configuration package group to stow."
    )
    parser.add_argument(
        "--unstow",
        action="store_true",
        help="Unstow the specified package group instead of stowing it.",
    )
    args = parser.parse_args()

    selected_pkgs = PKGS[args.package]
    is_unstow = args.unstow

    for pkg in selected_pkgs:
        try:
            if is_unstow:
                unstow(pkg)
                _log("INFO", f"Successfully unstowed package '{pkg}'.")
            else:
                stow(pkg)
                _log("INFO", f"Successfully stowed package '{pkg}'.")
        except subprocess.CalledProcessError as e:
            _log("ERROR", f"Failed to stow package '{pkg}': {e}")

    if is_unstow:
        return  # No need to switch session if we're just unstowing

    if args.package in SESSION_NAME:
        session = SESSION_NAME[args.package]
    else:
        session = SESSION_NAME["default"]

    try:
        switch(session)
        _log("INFO", f"Switched to session profile '{session}'.")
    except subprocess.CalledProcessError as e:
        _log("ERROR", f"Failed to switch session profile '{session}': {e}")


if __name__ == "__main__":
    main()
