"""Persist cabinet identity from P3 GAMESTATS into config.ini."""
from __future__ import annotations

from typing import Any, Optional

VALID_MACHINE_ROLES = frozenset({"M", "S"})


def normalize_machine_role(value: Optional[str]) -> str:
    if value is None:
        return ""
    role = str(value).strip().upper()
    if role in VALID_MACHINE_ROLES:
        return role
    return ""


def read_machine_identity(config) -> dict[str, Any]:
    """Read machine_role / bank_number / term_number from ExtendedConfigParser."""
    role = ""
    if config.has_option("TOPBOX", "MACHINE_ROLE"):
        role = normalize_machine_role(config.get("TOPBOX", "MACHINE_ROLE"))

    bank_number = 0
    if config.has_option("TOPBOX", "BANK_NUMBER"):
        bank_number = config.getint("TOPBOX", "BANK_NUMBER")

    term_number = 0
    if config.has_option("TOPBOX", "TERM_NUMBER"):
        term_number = config.getint("TOPBOX", "TERM_NUMBER")

    topbox_host = ""
    if config.has_option("TOPBOX", "TOPBOX_HOST"):
        topbox_host = config.get("TOPBOX", "TOPBOX_HOST").strip()

    bank_position = 0
    if config.has_option("TOPBOX", "BANK_POSITION"):
        try:
            bank_position = config.getint("TOPBOX", "BANK_POSITION")
        except ValueError:
            bank_position = 0

    pog_tid = ""
    if config.has_option("TOPBOX", "POG_TID"):
        pog_tid = config.get("TOPBOX", "POG_TID").strip().upper()

    return {
        "machine_role": role,
        "bank_number": bank_number,
        "term_number": term_number,
        "bank_position": max(0, bank_position),
        "topbox_host": topbox_host,
        "pog_tid": pog_tid,
    }


def persist_machine_identity_from_gamestats(
    config_path: str,
    *,
    machine_role: Optional[str],
    bank_number: Optional[int],
    term_number: Optional[int],
    pog_tid: Optional[str] = None,
) -> bool:
    """Write GAMESTATS header fields to config.ini when values change. Returns True if saved."""
    from extended_configparser.parser import ExtendedConfigParser

    role = normalize_machine_role(machine_role)
    bank = int(bank_number) if bank_number is not None else None
    term = int(term_number) if term_number is not None else None
    tid = (pog_tid or "").strip().upper()
    if len(tid) != 4:
        tid = ""

    config = ExtendedConfigParser()
    config.read(config_path)
    current = read_machine_identity(config)

    changed = False
    if role and role != current["machine_role"]:
        config.set("TOPBOX", "MACHINE_ROLE", role)
        changed = True
    if bank is not None and bank != current["bank_number"]:
        config.set("TOPBOX", "BANK_NUMBER", str(bank))
        changed = True
    if term is not None and term != current["term_number"]:
        config.set("TOPBOX", "TERM_NUMBER", str(term))
        config.set("TOPBOX", "MACHINE_NUMBER", str(term))
        changed = True
    if tid and tid != str(current.get("pog_tid") or ""):
        config.set("TOPBOX", "POG_TID", tid)
        changed = True

    if not changed:
        return False

    from config_ini_persist import write_config_ini

    return write_config_ini(config, config_path)


def persist_bank_position(config_path: str, position: int) -> bool:
    """Write operator BANK_POSITION (1..x). 0 clears. Returns True if saved."""
    from extended_configparser.parser import ExtendedConfigParser

    pos = max(0, int(position))
    config = ExtendedConfigParser()
    config.read(config_path)
    current = read_machine_identity(config)
    if pos == int(current.get("bank_position") or 0):
        return False
    if not config.has_section("TOPBOX"):
        config.add_section("TOPBOX")
    config.set("TOPBOX", "BANK_POSITION", str(pos))
    from config_ini_persist import write_config_ini

    return write_config_ini(config, config_path)
