"""BooruGacha Combine — merge, deduplicate, and filter tag lists."""

from ..data import format_weighted_tag, parse_weighted_tag


class _FlexibleInputs(dict):
    """Accepts any dynamically-named input from the frontend."""

    def __init__(self, fixed: dict | None = None):
        if fixed:
            self.update(fixed)

    def __contains__(self, key):
        return True

    def __getitem__(self, key):
        if key in self.keys():
            return super().__getitem__(key)
        return ("STRING", {"forceInput": True})


class BooruGachaCombine:
    """Merges multiple comma-separated tag inputs into a single
    deduplicated list. Earlier inputs take priority when duplicates
    are found (preserving weight from the first occurrence).

    An optional ``BANLIST`` input hard-filters any banned tags
    from the final output. Add/remove tag inputs via the node UI.
    """

    DESCRIPTION = (
        "Combines multiple tag inputs into one deduplicated list. "
        "Use the Add Input button to add more connections. "
        "Connect a ban_list for final-stage filtering."
    )

    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {},
            "optional": _FlexibleInputs(
                fixed={
                    "ban_list": (
                        "BANLIST",
                        {"tooltip": "Ban list — matched tags are removed."},
                    ),
                }
            ),
        }

    RETURN_TYPES = ("STRING", "STRING")
    RETURN_NAMES = ("tags", "debug_info")
    OUTPUT_TOOLTIPS = (
        "Comma-separated deduplicated tags",
        "Dedup and filter details",
    )
    FUNCTION = "combine"
    CATEGORY = "BooruGacha"

    def combine(self, ban_list: set | None = None, **kwargs):
        ban = ban_list or set()
        seen: set[str] = set()
        out_tags: list[str] = []
        dupes = 0
        banned = 0

        # Process inputs in sorted order (tags_1, tags_2, …)
        for key in sorted(kwargs):
            value = kwargs[key]
            if not isinstance(value, str) or not value.strip():
                continue

            for raw_tag in value.split(","):
                raw_tag = raw_tag.strip()
                if not raw_tag:
                    continue

                tag_text, weight = parse_weighted_tag(raw_tag)
                key_norm = tag_text.lower().replace(" ", "_")

                if key_norm in seen:
                    dupes += 1
                    continue

                if key_norm in ban or tag_text in ban:
                    banned += 1
                    continue

                seen.add(key_norm)
                out_tags.append(format_weighted_tag(tag_text, weight))

        debug = (
            f"{len(out_tags)} tags output, "
            f"{dupes} duplicates removed, "
            f"{banned} banned removed"
        )
        return (", ".join(out_tags), debug)
