#!/usr/bin/env python3
"""
    Check if all script dependencies are available.
    Does not go into venvs, dependencies need to be installed globally.
    Prints a list of which commands can be run and which can't.
    Basic binaries such as gnu coreutils are expected and not checked for.
"""

import os
import shutil
import subprocess
import configparser
from pathlib import Path
from typing import Dict, List, Tuple
import importlib

CHECK = "✅"
CROSS = "❌"

def check_command(cmd: str) -> Tuple[bool, str|None]:
    if shutil.which(cmd) is not None:
        return (True, None)
    else:
        return (False, f"Command '{cmd}' not found")

def check_env_var(var: str) -> Tuple[bool, str|None]:
    if var in os.environ:
        return (True, None)
    else:
        return (False, f"Environment variable '{var}' not set")

def check_python_lib(lib: str) -> Tuple[bool, str|None]:
    try:
        importlib.import_module(lib)
        return (True, None)
    except ImportError:
        return (False, f"Python library '{lib}' not found")

def check_stats_commands() -> List[Tuple[bool, str]]:
    """
    Checks if all the commands that are configured for the stats daemon
    can be executed.
    """
    results = []
    config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
    config_path = Path(config_home) / "stats/config.ini"

    if not config_path.exists():
        return [(False, f"Stats config not found at {config_path}")]

    config = configparser.ConfigParser(interpolation=None)
    config.read(config_path)

    for section in config.sections():
        if section.startswith('stat.'):
            cmd = config[section]['command']
            try:
                subprocess.run(cmd, shell=True, capture_output=True, check=True)
                results.append((True, None))
            except subprocess.CalledProcessError:
                results.append((False, f"Command '{cmd}' failed to run"))

    return results

def check_scripts() -> Dict[str, List[Tuple[bool, str|None]]]:
    """Run all checks for each script."""
    checks = {
        "check": [
            check_command("python3"),
            check_command("git"),
            check_command("sudo"),
            check_command("man"),
        ],
        "e-ink": [
            check_command("python3"),
            check_python_lib("PIL"),
        ],
        "indeel": [
            check_command("file"),
            check_command("magick"),
            check_command("dctfilename"),
            check_command("webpmux"),
            check_command("gifski"),
        ],
        "mover": [],
        "pushover": [
            check_env_var("PUSHOVER_APP_TOKEN"),
            check_env_var("PUSHOVER_USER_TOKEN"),
            check_command("curl"),
            check_python_lib("requests"),
        ],
        "stats": [
            check_command("python3"),
            check_command("sensors"),
            check_command("jq"),
            check_command("top"),
            check_command("free"),
            check_command("df"),
            check_python_lib("configparser"),
            check_python_lib("http"),
            *check_stats_commands(),
        ],
        "stats-collector": [
            check_command("python3"),
            check_python_lib("sqlalchemy"),
            check_python_lib("requests"),
        ],
        "syncwall": [
            check_command("wget"),
            check_command("wal"),
        ],
        "tclean": [
            check_command("python3"),
            check_command("transmission-remote"),
            check_python_lib("argparse"),
            check_python_lib("datetime"),
        ],
        "vc": [
            check_command("ffmpeg"),
            check_command("yt-dlp"),
            check_python_lib("argparse"),
        ],
        "vcmp": [
            check_command("ffmpeg"),
            check_command("ffprobe"),
            check_command("nice"),
            check_python_lib("pathlib"),
            check_python_lib("argparse"),
            check_python_lib("logging"),
            check_python_lib("tempfile"),
        ],
    }
    return checks

def check_git_updates() -> Tuple[bool, str|None]:
    try:
        script_dir = Path(__file__).parent.parent
        if not (script_dir / '.git').exists():
            return (False, "Not a git repository")
        original_dir = os.getcwd()
        os.chdir(script_dir)

        try:
            # git fetch
            subprocess.run(['git', 'fetch'], check=True, capture_output=True)

            # git status
            result = subprocess.run(['git', 'status'], check=True, capture_output=True, text=True)

            if "Your branch is up to date" in result.stdout:
                return (True, None)
            else:
                return (False, result.stdout)
        finally:
            os.chdir(original_dir)
    except subprocess.CalledProcessError as e:
        return (False, f"Git command failed: {e}")
    except Exception as e:
        return (False, f"Error checking git status: {e}")

def main():
    # First check git status
    git_status, git_message = check_git_updates()
    status = CHECK if git_status else CROSS
    print(f"{status} Repository status")
    if git_message:
        print(f"\t{status} {git_message}")
    print()  # Empty line for separation

    results = check_scripts()

    for script, checks in results.items():
        all_passed = all(result[0] for result in checks) if checks else True
        status = CHECK if all_passed else CROSS
        print(f"{status} {script}")

        for passed, message in checks:
            status = CHECK if passed else CROSS
            if message:
                print(f"\t{status} {message}")

if __name__ == "__main__":
    main()
