# manual_agregator/parser/handlers/attribute.py
from .base import FieldHandler
from ..utils import resolve_missing_text


class AttributeHandler(FieldHandler):
    def parse(self, field_name, config, soup, main_values, selectors, extracted):
        """
        Extracts an attribute value from the first element matching `selector`.
        Supports optional splitting via `splitBy` and `splitIndex`.

        Config keys:
        - selector: CSS selector (required)
        - attribute: attribute name to read (default: "value")
        - splitBy: optional delimiter to split the raw attribute value
        - splitIndex: index to pick after splitting
        - ifMissing/defaultValue: handled via resolve_missing_text
        - cast: optional ("int"|"float") to cast final value
        """
        sel = config.get("selector")
        if not sel:
            return resolve_missing_text(config)

        el = soup.select_one(sel)
        if not el:
            return resolve_missing_text(config)

        attr_name = config.get("attribute") or "value"
        raw = el.get(attr_name)
        if raw is None:
            return resolve_missing_text(config)

        # Normalize to string
        val = str(raw).strip()
        # Common cleanup for coordinates like "(50.1, 19.9)" or "[50.1, 19.9]"
        val_clean = val.strip().strip("[]()")

        split_by = config.get("splitBy")
        split_index = config.get("splitIndex")
        if split_by and split_index is not None:
            parts = [p.strip() for p in val_clean.split(split_by)]
            try:
                val_clean = parts[int(split_index)] if 0 <= int(split_index) < len(parts) else None
            except Exception:
                val_clean = None

        if val_clean is None or val_clean == "":
            return resolve_missing_text(config)

        # Optional casting
        cast = (config.get("cast") or "").lower().strip()
        if cast:
            try:
                if cast == "int":
                    return int(float(val_clean.replace(",", ".")))
                if cast == "float":
                    return float(val_clean.replace(",", "."))
            except Exception:
                # If casting fails, treat as missing per policy
                return resolve_missing_text(config)

        return val_clean
