"""Top-level entry point for building DMSData XML used in write operations."""
import warnings
import xml.etree.ElementTree as ET
from typing import Optional

from ecmind_blue_client.ecm.builder._dms_data_object import DmsDataObject


class DmsDataBuilder:
    """Builder for the DMSData XML structure used by dms.Index and similar write API methods.

    Use as a context manager or call ``to_xml()`` after configuring via ``object()``.
    """

    def __init__(self):
        # Initialize the root
        self._node = ET.Element("DMSData")
        # Initialize the archive node
        self._archive_node = ET.SubElement(self._node, "Archive")

    @property
    def query_language(self) -> int | None:
        """Numeric query language identifier for the DMSData request."""
        query_language = self._node.attrib.get("query_language", None)
        return int(query_language) if query_language else None

    @query_language.setter
    def query_language(self, value: int):
        self._node.attrib["query_language"] = f"{value}"

    @property
    def archive_id(self) -> int | None:
        """Numeric ID of the target archive."""
        archive_id = self._archive_node.attrib.get("id", None)
        return int(archive_id) if archive_id else None

    @archive_id.setter
    def archive_id(self, value: int):
        self._archive_node.attrib["id"] = str(value)

    @property
    def archive_name(self) -> str | None:
        """
        .. deprecated::
            Use ``archive_internal_name``, ``archive_osguid``, or ``archive_id`` instead.
            The display name is ambiguous and not recommended for archive identification.
        """
        return self._archive_node.attrib.get("name", None)

    @archive_name.setter
    def archive_name(self, value: str):
        warnings.warn(
            "archive_name is deprecated. Use archive_internal_name, archive_osguid, or archive_id instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        self._archive_node.attrib["name"] = value

    @property
    def archive_internal_name(self) -> str | None:
        """Internal name of the target archive."""
        return self._archive_node.attrib.get("internal_name", None)

    @archive_internal_name.setter
    def archive_internal_name(self, value: str):
        self._archive_node.attrib["internal_name"] = value

    @property
    def archive_osguid(self) -> str | None:
        """OS GUID of the target archive."""
        return self._archive_node.attrib.get("osguid", None)

    @archive_osguid.setter
    def archive_osguid(self, value: str):
        self._archive_node.attrib["osguid"] = value

    def object(self, internal_name_or_type_id: str | int, object_id: Optional[int] = None) -> DmsDataObject:
        """Creates or returns a ``DmsDataObject`` for the given object type.

        Args:
            internal_name_or_type_id (str | int): Internal name or numeric type ID of the object type.
            object_id (Optional[int]): Object ID of an existing object (for update operations).
                Pass ``None`` for new objects. Defaults to ``None``.

        Returns:
            DmsDataObject: The object data builder for this entry.
        """
        return DmsDataObject(self._archive_node, internal_name_or_type_id, object_id)

    def to_xml(self) -> bytes:
        """Generates the DMSData XML structure and returns it as UTF-8 encoded bytes.

        Returns:
            bytes: The serialised DMSData XML including XML declaration.
        """
        ET.indent(self._node, "    ")
        return ET.tostring(self._node, encoding="utf-8", xml_declaration=True)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        pass
