"""Read-only decoder for 1C DCS appearance-template payloads.

Appearance templates are a distinct XML family (``AppearanceTemplate``), not
DataCompositionSchema and not a spreadsheet document.  This decoder returns
only XML-backed rules and preserves the original carrier for any future
lossless writer work.
"""

from __future__ import annotations

import xml.etree.ElementTree as ET
from collections import Counter
from typing import Any

from .payload import decode_payload_lossless


def _local_name(tag: str) -> str:
    return tag.rsplit("}", 1)[-1]


def _child_text(node: ET.Element, name: str) -> str:
    child = next((item for item in node if _local_name(item.tag) == name), None)
    return "".join(child.itertext()).strip() if child is not None else ""


def inspect_appearance_payload(data: bytes) -> dict[str, Any]:
    """Decode a compressed appearance-template carrier without changing it."""

    decoded = decode_payload_lossless(data)
    payload = bytes(decoded.get("payload") or b"")
    start = payload.find(b"<?xml")
    if start < 0:
        start = payload.find(b"<AppearanceTemplate")
    end_marker = b"</AppearanceTemplate>"
    end = payload.find(end_marker, start) if start >= 0 else -1
    if start < 0 or end < 0:
        return {
            "status": "undecodable",
            "container": {"compression": decoded.get("compression"), "raw_bytes": decoded.get("raw_bytes"), "payload_bytes": decoded.get("payload_bytes")},
            "diagnostics": {"code": "APPEARANCE_XML_NOT_FOUND"},
        }
    xml_bytes = payload[start : end + len(end_marker)]
    try:
        root = ET.fromstring(xml_bytes.decode("utf-8-sig"))
    except (UnicodeDecodeError, ET.ParseError) as exc:
        return {"status": "undecodable", "diagnostics": {"code": "APPEARANCE_XML_INVALID", "message": str(exc)}}
    if _local_name(root.tag) != "AppearanceTemplate":
        return {"status": "unsupported", "diagnostics": {"code": "APPEARANCE_ROOT_NOT_CONFIRMED", "xml_root": _local_name(root.tag)}}
    items = []
    for ordinal, item in enumerate((node for node in root if _local_name(node.tag) == "item"), start=1):
        parameter, value = _child_text(item, "parameter"), _child_text(item, "value")
        items.append({"ordinal": ordinal, "parameter": parameter, "value": value})
    appearances = []
    for ordinal, appearance in enumerate((node for node in root.iter() if _local_name(node.tag) == "appearance"), start=1):
        rules = []
        for item in (node for node in appearance if _local_name(node.tag) == "item"):
            value_node = next((child for child in item if _local_name(child.tag) == "value"), None)
            rule: dict[str, Any] = {"parameter": _child_text(item, "parameter"), "value": _child_text(item, "value")}
            if value_node is not None:
                value_type = value_node.attrib.get("{http://www.w3.org/2001/XMLSchema-instance}type") or value_node.attrib.get("type")
                if value_type:
                    rule["value_type"] = value_type
                if value_node.attrib:
                    rule["value_attributes"] = {key.rsplit("}", 1)[-1]: value for key, value in value_node.attrib.items()}
                nested_values = []
                for child in value_node.iter():
                    if child is value_node or list(child):
                        continue
                    nested_values.append({
                        "tag": _local_name(child.tag),
                        "value": "".join(child.itertext()).strip(),
                        **({"attributes": {key.rsplit("}", 1)[-1]: value for key, value in child.attrib.items()}} if child.attrib else {}),
                    })
                if nested_values:
                    rule["value_children"] = nested_values
            rules.append(rule)
        appearances.append({"ordinal": ordinal, "rules": rules})
    tag_counts = Counter(_local_name(node.tag) for node in root.iter())
    return {
        "status": "ok",
        "container": {"compression": decoded.get("compression"), "raw_bytes": decoded.get("raw_bytes"), "payload_bytes": decoded.get("payload_bytes"), "xml_offset": start, "xml_bytes": len(xml_bytes), "xml_root": "AppearanceTemplate"},
        "items": items,
        "appearances": appearances,
        "outline": {"tag_counts": dict(sorted(tag_counts.items(), key=lambda item: item[0].casefold()))},
        "diagnostics": {"write": "unsupported_until_reverse_codec_fixture"},
    }
