"""XML utilities for Tableau template manipulation."""

from __future__ import annotations

from pathlib import Path
from typing import Dict


def _load_lxml():
    try:
        from lxml import etree
    except ImportError as exc:  # pragma: no cover - optional dependency
        raise ImportError(
            "lxml is required for Tableau template XML operations. "
            "Install with: pip install g-gremlin[tableau]"
        ) from exc
    return etree


def get_extract_relpath_from_template(twb_path: Path) -> str:
    """
    Read template TWB to find the hyper connection path.

    Returns the relative path the template expects (e.g., "Data/Datasources/data.hyper").
    """
    etree = _load_lxml()
    tree = etree.parse(str(twb_path))
    root = tree.getroot()

    conns = root.xpath("//*[local-name()='connection' and @class='hyper']")
    if not conns:
        return "Data/Datasources/data.hyper"

    dbname = conns[0].get("dbname")
    if not dbname:
        return "Data/Datasources/data.hyper"
    return dbname


def update_template_captions(
    twb_path: Path,
    role_mapping: Dict[str, str],
    output_path: Path,
) -> Path:
    """
    Update column captions for better UX (optional).

    Maps canonical roles to the original CSV column names.
    """
    etree = _load_lxml()
    tree = etree.parse(str(twb_path))
    root = tree.getroot()

    for canonical_role, csv_column in role_mapping.items():
        xpath = f"//*[local-name()='column' and @name='[{canonical_role}]']"
        for col in root.xpath(xpath):
            col.set("caption", csv_column)

    tree.write(str(output_path), encoding="utf-8", xml_declaration=True)
    return output_path


__all__ = ["get_extract_relpath_from_template", "update_template_captions"]
