#!/usr/bin/env python3
import argparse
import configparser
import os
import sys
import urllib3
import redfish
from datetime import datetime

try:
    from cryptography.fernet import Fernet, InvalidToken
except ImportError:
    sys.exit("Error: 'cryptography' package is required.  Run: pip install cryptography")

DEFAULT_CREDENTIALS_FILE = "/root/cron_serverlists/credentials.ini"
DEFAULT_KEYFILE_NAME = "secret.key"


def log(message, is_error=False):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    stream = sys.stderr if is_error else sys.stdout
    print(f"[{timestamp}] {message}", file=stream)


def resolve_credentials_path(cli_path):
    """Resolve credentials path. Prefer explicit CLI path, then search common locations."""
    if cli_path and os.path.exists(cli_path):
        return cli_path

    candidates = []
    if cli_path:
        candidates.append(cli_path)
    candidates.append(os.path.join(os.getcwd(), "credentials.ini"))
    if DEFAULT_CREDENTIALS_FILE not in candidates:
        candidates.append(DEFAULT_CREDENTIALS_FILE)

    for candidate in candidates:
        if os.path.exists(candidate):
            return candidate

    log(
        "Error: credentials file not found. Looked in: " + ", ".join(candidates),
        is_error=True,
    )
    sys.exit(1)


def resolve_keyfile(cli_keyfile, credentials_path):
    """Resolve keyfile path. Prefer explicit --keyfile, else search next to credentials file."""
    if cli_keyfile:
        return cli_keyfile if os.path.exists(cli_keyfile) else None

    candidate = os.path.join(os.path.dirname(credentials_path), DEFAULT_KEYFILE_NAME)
    if os.path.exists(candidate):
        return candidate

    return None


def load_fernet(keyfile):
    """Load Fernet instance from the key file created by set_password.py."""
    if not os.path.exists(keyfile):
        log(f"Error: key file not found: {keyfile}", is_error=True)
        sys.exit(1)
    with open(keyfile, "rb") as fh:
        key = fh.read()
    try:
        return Fernet(key)
    except ValueError:
        log(f"Error: invalid key format in key file: {keyfile}", is_error=True)
        sys.exit(1)


def is_fernet_token(value):
    return isinstance(value, str) and value.startswith("gAAAA")


def decrypt_password(encrypted_password, fernet):
    """Decrypt password encrypted by set_password.py, or pass through plaintext."""
    if not is_fernet_token(encrypted_password):
        return encrypted_password
    if fernet is None:
        log(
            "Error: encrypted password detected but key file was not found. "
            "Use --keyfile /path/to/secret.key.",
            is_error=True,
        )
        sys.exit(1)
    try:
        return fernet.decrypt(encrypted_password.encode()).decode()
    except InvalidToken:
        log("Error: failed to decrypt password. Check that --keyfile matches the credentials file.", is_error=True)
        sys.exit(1)


def load_ilo_credentials(path, fernet):
    config = configparser.ConfigParser()
    config.read(path)

    section = "ilo_credentials"
    if not config.has_section(section):
        log(f"Error: missing [{section}] section in {path}", is_error=True)
        sys.exit(1)

    username = config.get(section, "username", fallback="root")
    encrypted_password = config.get(section, "password", fallback=None)
    if not encrypted_password:
        log(f"Error: missing password in [{section}] section of {path}", is_error=True)
        sys.exit(1)

    password = decrypt_password(encrypted_password, fernet)
    return username, password


# Suppress SSL warnings for self-signed iLO certificates
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

parser = argparse.ArgumentParser(description="Get the power status of an HPE server via iLO Redfish")
parser.add_argument("hostname", help="iLO hostname or IP address")
parser.add_argument("-c", "--credentials", default=None,
                    help="Path to credentials file (default: auto-detected credentials.ini)")
parser.add_argument("--keyfile", default=None,
                    help="Path to Fernet key file for decrypting passwords (default: auto-detected secret.key)")
args = parser.parse_args()

cred_path = resolve_credentials_path(args.credentials)
keyfile = resolve_keyfile(args.keyfile, cred_path)
fernet = load_fernet(keyfile) if keyfile else None

LOGIN_ACCOUNT, LOGIN_PASSWORD = load_ilo_credentials(cred_path, fernet)

BASE_URL = f"https://{args.hostname}"

REDFISHOBJ = redfish.RedfishClient(
    base_url=BASE_URL,
    username=LOGIN_ACCOUNT,
    password=LOGIN_PASSWORD,
)
REDFISHOBJ.login(auth="session")

sys_response = REDFISHOBJ.get("/redfish/v1/Systems/1/")
power_state = sys_response.dict.get("PowerState", "Unknown")

log(f"Power State: {power_state}")

REDFISHOBJ.logout()
