"""
workflow_check.py — System check workflow for ES24N IOM controllers.

Queries current network settings and firmware versions from one or both IOMs
via either a serial connection (for IOMs not yet on the network) or a direct
network connection (for IOMs already reachable via their management IP).
No changes are made — this is a read-only diagnostic workflow.
"""

import time

from redfish import _redfish_request, _get_iom_fw_version, _get_fabric_fw_version
from workflow_serial import (
    detect_serial_device,
    open_serial_connection,
    close_serial_connection,
    _login_serial_console,
    _serial_redfish_request,
)
from ui import (
    _c, C,
    banner, rule, draw_table,
    info, ok, warn, error,
    prompt, prompt_ip, prompt_password,
)


# ── Shared helpers ─────────────────────────────────────────────────────────────

def _parse_network_data(data: dict) -> tuple:
    """
    Extract (dhcp_enabled, ip, gateway, netmask, origin) from a
    Redfish EthernetInterfaces/1 response dict.
    """
    dhcp_enabled = (
        data.get("DHCPv4", {}).get("DHCPEnabled", False) or
        data.get("DHCPv6", {}).get("DHCPEnabled", False)
    )
    addrs = data.get("IPv4StaticAddresses") or data.get("IPv4Addresses", [])
    if addrs:
        addr    = addrs[0]
        ip      = addr.get("Address",    "--")
        gateway = addr.get("Gateway",    "--")
        netmask = addr.get("SubnetMask", "--")
    else:
        ip = gateway = netmask = "--"

    origin = (
        data.get("IPv4Addresses", [{}])[0].get("AddressOrigin", "Unknown")
        if data.get("IPv4Addresses")
        else ("DHCP" if dhcp_enabled else "Static")
    )
    return dhcp_enabled, ip, gateway, netmask, origin


def _print_results(net_rows: list, fw_rows: list):
    rule("Network Settings")
    draw_table(
        ["IOM", "Mode", "Origin", "IP Address", "Gateway", "Subnet Mask"],
        net_rows,
        [5, 10, 8, 16, 16, 16],
    )
    print()

    rule("Firmware Versions")
    draw_table(
        ["IOM", "IOM Firmware", "Fabric Firmware"],
        fw_rows,
        [5, 32, 24],
    )
    print()


# ── Serial check ───────────────────────────────────────────────────────────────

def _check_via_serial():
    banner()
    rule("System Check -- Serial Connection")

    device = detect_serial_device()
    if not device:
        error("Could not detect a serial device. Returning to main menu.")
        time.sleep(2)
        return

    ser = open_serial_connection(device)
    if not ser:
        error("Could not open serial port. Returning to main menu.")
        time.sleep(2)
        return

    print()
    logged_in, password = _login_serial_console(ser)
    if not logged_in:
        error("Could not log in to IOM console. Returning to main menu.")
        close_serial_connection(ser, device)
        time.sleep(2)
        return

    rule("Querying IOM Status")
    info("Querying network settings and firmware versions via serial console...")
    print()

    net_rows = []
    fw_rows  = []

    for iom in ("IOM1", "IOM2"):
        # ── Network settings ───────────────────────────────────────────────────
        net_ok, net_data = _serial_redfish_request(
            ser, password, "GET",
            f"/redfish/v1/Managers/{iom}/EthernetInterfaces/1",
        )
        if net_ok and isinstance(net_data, dict):
            dhcp, ip, gw, nm, origin = _parse_network_data(net_data)
            mode = _c(C.CYN, "DHCP") if dhcp else _c(C.GRN, "Static")
            net_rows.append([iom, mode, origin, ip, gw, nm])
        else:
            net_rows.append([iom, _c(C.RED, "No response"), "--", "--", "--", "--"])
            error(f"{iom} network query failed: {net_data}")

        # ── IOM firmware version ───────────────────────────────────────────────
        iom_ok, iom_data = _serial_redfish_request(
            ser, password, "GET",
            f"/redfish/v1/Managers/{iom}",
        )
        iom_ver = (
            iom_data.get("FirmwareVersion", "Unknown")
            if (iom_ok and isinstance(iom_data, dict))
            else _c(C.RED, "Unreachable")
        )

        # ── Fabric card firmware version ───────────────────────────────────────
        fab_ok, fab_data = _serial_redfish_request(
            ser, password, "GET",
            f"/redfish/v1/Chassis/{iom}/NetworkAdapters/1",
        )
        fab_ver = (
            (fab_data.get("Oem", {})
                     .get("Version", {})
                     .get("ActiveFirmwareVersion", "Unknown"))
            if (fab_ok and isinstance(fab_data, dict))
            else _c(C.RED, "Unreachable")
        )

        fw_rows.append([iom, iom_ver, fab_ver])

    _print_results(net_rows, fw_rows)
    close_serial_connection(ser, device)


# ── Network check ──────────────────────────────────────────────────────────────

def _check_via_network():
    banner()
    rule("System Check -- Network Connection")

    print()
    password = prompt_password()
    print()
    ip = prompt_ip("  IOM IP address (either IOM1 or IOM2)")

    iom_list = [("IOM1", ip), ("IOM2", ip)]

    rule("Querying IOM Status")
    info("Querying network settings and firmware versions over the network...")
    print()

    net_rows = []
    fw_rows  = []

    for iom, ip in iom_list:
        # ── Network settings ───────────────────────────────────────────────────
        net_ok, net_data = _redfish_request(
            password, "GET",
            f"/redfish/v1/Managers/{iom}/EthernetInterfaces/1",
            host=ip,
        )
        if net_ok and isinstance(net_data, dict):
            dhcp, ip_addr, gw, nm, origin = _parse_network_data(net_data)
            mode = _c(C.CYN, "DHCP") if dhcp else _c(C.GRN, "Static")
            net_rows.append([iom, mode, origin, ip_addr, gw, nm])
        else:
            net_rows.append([iom, _c(C.RED, "No response"), "--", "--", "--", "--"])
            error(f"{iom} network query failed: {net_data}")

        # ── Firmware versions (reuse shared redfish helpers) ───────────────────
        iom_ver = _get_iom_fw_version(password, ip, iom)
        fab_ver = _get_fabric_fw_version(password, ip, iom)
        fw_rows.append([iom, iom_ver, fab_ver])

    _print_results(net_rows, fw_rows)


# ── Top-level entry point ──────────────────────────────────────────────────────

def system_check_workflow():
    banner()
    rule("System Check")

    print("  How do you want to connect to the IOM(s)?")
    print()
    print(f"    {_c(C.BOLD, '1')}  Serial connection   (IOM not yet on the network)")
    print(f"    {_c(C.BOLD, '2')}  Network connection  (IOM reachable via management IP)")
    print(f"    {_c(C.BOLD, '3')}  Cancel")
    print()

    while True:
        choice = prompt("Select [1/2/3]")
        if choice in ("1", "2", "3"):
            break
        warn("Please enter 1, 2, or 3.")

    if choice == "1":
        _check_via_serial()
    elif choice == "2":
        _check_via_network()
    # choice == "3" returns to main menu
