"""Parser for ``<Object>`` elements in DMSContent responses."""
import xml.etree.ElementTree as ET

from ecmind_blue_client.ecm.parser._dms_content_document_variant import (
    DmsContentDocumentVariant,
)
from ecmind_blue_client.ecm.parser._dms_content_object_base_params import (
    DmsContentObjectBaseParams,
)
from ecmind_blue_client.ecm.parser._dms_content_object_field import (
    DmsContentObjectField,
)
from ecmind_blue_client.ecm.parser._dms_content_object_file_properties import (
    DmsContentObjectFileProperties,
)
from ecmind_blue_client.ecm.parser._dms_content_object_multi_field import (
    DmsContentObjectMultiField,
)
from ecmind_blue_client.ecm.parser._dms_content_object_rights import (
    DmsContentObjectRights,
)
from ecmind_blue_client.ecm.parser._dms_content_object_table_field import (
    DmsContentObjectTableField,
)


class DmsContentObject:
    """Represents an ``<Object>`` element within a HOL ``<ObjectType>``.

    Provides access to index fields, table-dialog fields, multi-fields, document variants,
    child object hierarchies, and optional sections (rights, base params, file properties).
    """

    def __init__(self, node: ET.Element, archive: ET.Element):
        self._node = node
        self._archive = archive
        self._fields = {node.attrib["internal_name"]: DmsContentObjectField(node) for node in self._node.findall("Fields/Field")}
        self._table_fields = {
            node.attrib["internal_name"]: DmsContentObjectTableField(node) for node in self._node.findall("TableFields/TableField")
        }

    @property
    def id(self) -> int:
        """Numeric object ID."""
        return int(self._node.get("id", "-1"))

    @property
    def fields(self) -> dict[str, DmsContentObjectField]:
        """Index fields of this object, keyed by ``internal_name``."""
        return self._fields

    @property
    def table_fields(self) -> dict[str, DmsContentObjectTableField]:
        """Table-dialog fields of this object, keyed by ``internal_name``."""
        return self._table_fields

    @property
    def rights(self) -> DmsContentObjectRights | None:
        """Access rights for this object (requires ``rights=1`` in the query)."""
        rights = self._node.find("Rights")
        if rights is None:
            return None
        return DmsContentObjectRights(rights)

    @property
    def base_params(self) -> DmsContentObjectBaseParams | None:
        """Base parameters (creator, timestamps, links, etc.) for this object (requires ``baseParams=1`` in the query)."""
        base_params = self._node.find("BaseParams")
        if base_params is None:
            return None
        return DmsContentObjectBaseParams(base_params)

    @property
    def file_properties(self) -> DmsContentObjectFileProperties:
        """File properties (size, MIME type, page count) for this document object.

        Raises:
            ValueError: If the ``<FileProperties>`` element is absent (requires ``fileinfo=True`` and a document type).
        """
        file_properties = self._node.find("FileProperties")
        if file_properties is None:
            raise ValueError("<FileProperties> tag in <Object> not found. This tag is only available for documents and fileinfo=True.")
        return DmsContentObjectFileProperties(file_properties)

    @property
    def document_variants(self) -> list[DmsContentDocumentVariant] | None:
        """All document variants from ``<DocumentVariants>``, or ``None`` if the element is absent.

        Returns ``None`` when ``variants`` was not requested on the query (element not sent by
        the server), and an empty list when variants were requested but the document has none.
        """
        dv_element = self._node.find("DocumentVariants")
        if dv_element is None:
            return None
        return [DmsContentDocumentVariant(variant) for variant in dv_element.findall("DocumentVariant")]

    @property
    def multi_fields(self) -> dict[str, DmsContentObjectMultiField]:
        """Returns all ``<MultiField>`` elements from ``<MultiFields>``, keyed by ``internal_name``.

        Returns:
            dict[str, DmsContentObjectMultiField]: Internal name → multi-field mapping, may be empty.
        """
        return {node.get("internal_name", ""): DmsContentObjectMultiField(node) for node in self._node.findall("MultiFields/MultiField")}

    @property
    def export_depth(self) -> int | None:
        """Export depth of this object, or ``None`` if the attribute is absent."""
        value = self._node.get("export_depth")
        return int(value) if value is not None else None

    def external_object_types(self):
        """Yields all ``<ObjectType>`` elements from ``<ExternalObjects>/<Archive>`` sections.

        Each yielded item is a ``DmsContentObjectType`` associated with the enclosing
        ``<Archive>`` element.

        Yields:
            DmsContentObjectType: Parsed external object types.
        """
        from ecmind_blue_client.ecm.parser._dms_content_object_type import (
            DmsContentObjectType,
        )

        for archive_node in self._node.findall("ExternalObjects/Archive"):
            for ot_node in archive_node.findall("ObjectType"):
                yield DmsContentObjectType(ot_node, archive_node)
