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

from ecmind_blue_client.ecm.parser._dms_content_lol_row_table_field import DmsContentLolRowTableField
from ecmind_blue_client.ecm.parser._dms_content_object import DmsContentObjectRights
from ecmind_blue_client.ecm.parser._dms_content_object_row_field import (
    DmsContentObjectRowField,
)


class DmsContentRow:
    """Represents a ``<Row>`` element within a LOL ``<Rowset>``.

    Each row contains positional ``<Value>`` elements whose metadata (internal name,
    datatype, etc.) is resolved from the corresponding ``<Column>`` definitions.
    Optionally, rows may also contain embedded ``<TableField>`` elements.
    """

    def __init__(
        self,
        node: ET.Element,
        column_nodes: list[ET.Element],
        table_field_columns: dict[str, list[str]] | None = None,
    ):
        """Args:
            node: The ``<Row>`` XML element.
            column_nodes: Ordered list of ``<Column>`` elements from ``Rowset/Columns``.
            table_field_columns: Optional mapping of table field ``internal_name`` to
                ordered column name strings, used to resolve ``<TableField>`` sub-rows.
        """
        self._node = node
        self._table_field_columns = table_field_columns or {}
        value_nodes = self._node.findall("Value")

        self._fields: dict[str, DmsContentObjectRowField] = {}
        for i, value_node in enumerate(value_nodes):
            field = DmsContentObjectRowField(column_nodes[i], value_node, self.id)
            self._fields[field.internal_name] = field

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

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

    @property
    def table_fields(self) -> dict[str, DmsContentLolRowTableField]:
        """Returns all embedded ``<TableField>`` elements from this LOL row.

        Column names are resolved from the ``Rowset/Columns/TableField`` declarations
        passed in at construction time. If no column definitions were provided (e.g.
        when parsing outside a LOL context), all column lists will be empty.

        Returns:
            dict[str, DmsContentLolRowTableField]: Internal name → table field mapping,
            may be empty if the row contains no embedded table fields.
        """
        return {
            tf_node.get("internal_name", ""): DmsContentLolRowTableField(
                tf_node, self._table_field_columns.get(tf_node.get("internal_name", ""), [])
            )
            for tf_node in self._node.findall("TableField")
        }

    @property
    def rights(self) -> DmsContentObjectRights:
        """Access rights for this row.

        Raises:
            ValueError: If the ``<Rights>`` element is absent (requires ``rights=1`` in the query).
        """
        rights = self._node.find("Rights")
        if rights is None:
            raise ValueError("<Rights> tag in <Object> not found. This tag is only available if rights=1 in the <DmsQuery>.")
        return DmsContentObjectRights(rights)
