"""Filter normalizer — detect common filter patterns across artifacts."""
from __future__ import annotations

from collections import defaultdict
from typing import Any, Dict, List

from ..contracts import FilterPredicate, LogicArtifact


class FilterNormalizer:
    """Analyze and normalize filter predicates across multiple artifacts.

    Identifies common business-rule filters (e.g. status='Active') that
    appear repeatedly across queries and scripts.
    """

    def find_common_filters(
        self, artifacts: List[LogicArtifact], min_occurrences: int = 2
    ) -> List[Dict[str, Any]]:
        """Find filter patterns that appear in multiple artifacts.

        Returns a list of common filter dicts sorted by occurrence count.
        """
        # Group filters by normalized column name
        column_groups: Dict[str, List[Dict[str, Any]]] = defaultdict(list)

        for art in artifacts:
            for f in art.objects.filters:
                col_key = f.column.lower().split(".")[-1].strip() if f.column else ""
                if not col_key:
                    continue
                column_groups[col_key].append({
                    "artifact_id": art.artifact_id,
                    "source_type": art.source_type.value,
                    "column": f.column,
                    "operator": f.operator.value,
                    "value": f.value,
                    "source_clause": f.source_clause,
                    "is_having": f.is_having,
                })

        results = []
        for col, entries in sorted(column_groups.items(), key=lambda x: -len(x[1])):
            if len(entries) < min_occurrences:
                continue
            # Deduplicate values
            unique_values = list(dict.fromkeys(e["value"] for e in entries if e["value"]))
            unique_ops = list(dict.fromkeys(e["operator"] for e in entries))
            artifact_ids = list(dict.fromkeys(e["artifact_id"] for e in entries))

            results.append({
                "column": col,
                "occurrences": len(entries),
                "artifact_count": len(artifact_ids),
                "operators": unique_ops,
                "values": unique_values[:5],
                "is_business_rule": len(artifact_ids) >= min_occurrences,
                "examples": [e["source_clause"] for e in entries[:3]],
            })

        return results

    def normalize_filters(
        self, artifacts: List[LogicArtifact]
    ) -> List[Dict[str, Any]]:
        """Normalize all filters, grouping by column and detecting patterns.

        Returns all filters grouped and annotated.
        """
        all_filters: List[Dict[str, Any]] = []
        for art in artifacts:
            for f in art.objects.filters:
                col_key = f.column.lower().split(".")[-1].strip() if f.column else ""
                all_filters.append({
                    "column": col_key or f.column,
                    "operator": f.operator.value,
                    "value": f.value,
                    "source_clause": f.source_clause,
                    "is_having": f.is_having,
                    "artifact_id": art.artifact_id,
                    "source_type": art.source_type.value,
                })

        return all_filters

    def detect_having_patterns(
        self, artifacts: List[LogicArtifact]
    ) -> List[Dict[str, Any]]:
        """Extract HAVING clause patterns (post-aggregation filters)."""
        having: List[Dict[str, Any]] = []
        for art in artifacts:
            for f in art.objects.filters:
                if f.is_having:
                    having.append({
                        "artifact_id": art.artifact_id,
                        "column": f.column,
                        "operator": f.operator.value,
                        "value": f.value,
                        "source_clause": f.source_clause,
                    })
        return having
