from __future__ import annotations

from typing import Any, Mapping


def _family_config(profile_name: str) -> tuple[str, int, int, int]:
    lowered = profile_name.lower()
    if "30i" in lowered or "ncg" in lowered:
        return ("30i", 32, 2, 4)
    if "0id" in lowered or "0dn" in lowered:
        return ("0i-D", 24, 1, 2)
    if "fwlibe64" in lowered:
        return ("e64", 8, 1, 2)
    return ("generic", 8, 1, 2)


def make_default_state(profile: Mapping[str, Any]) -> dict[str, Any]:
    profile_name = str(profile.get("profile_name", "FWLIB64"))
    family, default_axes, max_path, max_spindles = _family_config(profile_name)
    max_axis = int(profile.get("max_axis_hint") or default_axes)
    axis_names = [
        "X",
        "Y",
        "Z",
        "A",
        "B",
        "C",
        "U",
        "V",
        "W",
        "P",
        "Q",
        "R",
    ]
    while len(axis_names) < max_axis:
        axis_names.append(f"A{len(axis_names) + 1}")

    spindle_names = [f"S{i}" for i in range(1, max_spindles + 1)]
    programs = [
        {"number": 1, "comment": "MAIN", "length": 128},
        {"number": 100, "comment": "TOOLCHANGE", "length": 84},
    ]

    return {
        "sysinfo": {
            "addinfo": 0,
            "max_axis": max_axis,
            "cnc_type": family[:2].ljust(2),
            "mt_type": "M ",
            "series": family[:4].ljust(4),
            "version": "A1.0",
            "axes": str(max_axis).rjust(2, "0"),
        },
        "statinfo": {
            "aut": 1,
            "run": 3,
            "motion": 1,
            "mstb": 0,
            "emergency": 0,
            "alarm": 0,
            "edit": 0,
        },
        "paths": {"current": 1, "max": max_path},
        "dynamic": {
            "alarm": 0,
            "prgnum": 1,
            "prgmnum": 1,
            "seqnum": 120,
            "actf": 1500,
            "acts": 3200,
            "axes": {
                axis_names[0]: {"absolute": 123456, "machine": 123450, "relative": 6, "distance": 0},
                axis_names[1]: {"absolute": -22000, "machine": -22010, "relative": 10, "distance": 0},
                axis_names[2]: {"absolute": 8000, "machine": 7990, "relative": 10, "distance": 0},
            },
        },
        "actf": 1500,
        "acts": 3200,
        "acts2": [3200] + [0] * (max_spindles - 1),
        "axis_names": axis_names[:max_axis],
        # Per-axis position decimal places served by cnc_getfigure (command 0x00d3).
        # Default every configured axis to 0 ⇒ 10^0 = 1.0 scale, leaving existing
        # position reads unchanged. mock_patch can override individual axes.
        "position_figures": {name: 0 for name in axis_names[:max_axis]},
        "spindle_names": spindle_names,
        "parameters": {
            "6711": {"type": "long", "value": 1, "decimal": 0, "description": "example parameter"},
            "6712": {"type": "long", "value": 500, "decimal": 0, "description": "example parameter"},
        },
        "pmc": {
            "R": {
                "100": {"type": "byte", "value": 0},
                "101": {"type": "byte", "value": 1},
                "102": {"type": "byte", "value": 0},
            },
        },
        "macros": {
            "100": {"value": 12345, "decimal": 3},
            "101": {"value": 98765, "decimal": 3},
        },
        "alarms": [
            {"alm_no": 0, "type": 0, "axis": 0, "msg": ""},
        ],
        "operator_messages": [
            {"number": 200, "type": 0, "char_num": 12, "data": "READY"},
        ],
        "program": {
            "current": 1,
            "main": 1,
            "sequence": 120,
            "block_count": 42,
            "executing": "%\nO0001\nG90 G54 G00 X0 Y0\nM30\n%",
            "executing_path": "//CNC_MEM/USER/PATH1/O0001",
            "directory": programs,
        },
        "spindle": {
            "meter": [
                {"name": spindle_names[0], "value": 56, "unit": "%"},
                {"name": spindle_names[1], "value": 0, "unit": "%"},
            ],
            "servo_meter": [
                {"name": axis_names[0], "value": 14, "unit": "%"},
                {"name": axis_names[1], "value": 8, "unit": "%"},
                {"name": axis_names[2], "value": 5, "unit": "%"},
            ],
            "load": [
                {"name": spindle_names[0], "load": 56, "speed": 3200},
                {"name": spindle_names[1], "load": 0, "speed": 0},
            ],
            "gear": [1] * max_spindles,
            "max_rpm": [6000] * max_spindles,
        },
        "timers": {
            "power_on": 86400,
            "operating": 7200,
            "cutting": 3600,
            "cycle": 95,
        },
        "operation_mode": {"mode": 1, "name": "MEM"},
        "diagnostics": {
            "300": {"type": "long", "value": 14, "description": "servo load X"},
            "301": {"type": "long", "value": 8, "description": "servo load Y"},
            "302": {"type": "long", "value": 5, "description": "servo load Z"},
        },
        "forced_errors": {},
    }
