from dataclasses import dataclass, field
from typing import Dict, List, Any, Optional, Union


class FilterOperator:
    """
    Constants for standard filtering operators.
    """
    EQ = "eq"
    NE = "ne"
    GT = "gt"
    GTE = "gte"
    LT = "lt"
    LTE = "lte"
    IN = "in"
    NIN = "nin"
    CONTAINS = "contains"
    SEARCH = "_search"


class GroupSummaryType:
    """
    Aggregate methods for group summary types.
    """
    SUM = "Sum"
    AVG = "Avg"
    MAX = "Max"
    MIN = "Min"
    COUNT = "Count"

class GroupOption:
    def __init__(self, property_name: str):
        self.property_name = property_name

class GroupSummary:
    def __init__(self, type: str, property_name: str):
        self.type = type
        self.property_name = property_name


class SortOption:
    def __init__(self, field: str, order: str = "asc"):
        self.field = field
        self.order = order


class SearchQuery:
    """
    Generic class to represent JSON request structure.
    """
    @classmethod
    def from_dict(cls, data: dict):
        """
        Helper to convert dictionary coming from endpoint to SearchQuery object.
        """

        svc_name = data.get("serviceName") or data.get("service_name") or "pipeline_runner"

        return cls(
            filters=data.get("filters"),
            sort=data.get("sort"),
            limit=data.get("limit", 1000),
            page=data.get("page", 1),
            size=data.get("size", 50),
            service_name=svc_name
        )


    def __init__(self,
                 filters: Optional[Dict[str, Any]] = None,
                 sort: Optional[List[SortOption]] = None,
                 limit: int = 1000,
                 page: int = 1,
                 size: int = 50,
                 service_name: str = "pipeline_runner"):

        self.filters = filters if filters is not None else {}
        self.limit = limit
        self.page = page
        self.size = size
        self.service_name = service_name

        self.sort: List[SortOption] = []
        if sort:
            for s in sort:
                if isinstance(s, SortOption):
                    self.sort.append(s)
                elif isinstance(s, dict):
                    self.sort.append(SortOption(field=s.get("field"), order=s.get("order", "asc")))


    def to_dict(self) -> dict:
        """
        Convert SearchQuery to a dictionary matching the API expected JSON format.
        """
        data = {
            "filters": self.filters,
            "limit": self.limit,
            "page": self.page,
            "size": self.size,
            "serviceName": self.service_name,
        }
        if self.sort:
            data["sort"] = [{"field": s.field, "order": s.order} for s in self.sort]
        return data

class GroupSearchQuery:
    """
    Generic class to represent JSON request structure.
    """
    @classmethod
    def from_dict(cls, data: dict):
        """
        Helper to convert dictionary coming from endpoint to SearchQuery object.
        """

        svc_name = data.get("serviceName") or data.get("service_name") or "pipeline_runner"

        return cls(
            filters=data.get("filters"),
            service_name=svc_name,
            groups=data.get("groups"),
            group_summaries=data.get("groupSummaries")
        )


    def __init__(self,
                 filters: Optional[Dict[str, Any]] = None,
                 service_name: str = "pipeline_runner",
                 groups: Optional[List[Union[GroupOption, dict]]] = None,
                 group_summaries: Optional[List[Union[GroupSummary, dict]]] = None):

        self.filters = filters if filters is not None else {}
        self.service_name = service_name


        # New grouping feature
        self.groups: List[GroupOption] = []
        if groups:
            for g in groups:
                if isinstance(g, GroupOption):
                    self.groups.append(g)
                elif isinstance(g, dict) and g.get("propertyName"):
                    self.groups.append(GroupOption(property_name=g.get("propertyName")))


        # GroupSummaries
        self.group_summaries: List[GroupSummary] = []
        if group_summaries:
            for gs in group_summaries:
                if isinstance(gs, GroupSummary):
                    self.group_summaries.append(gs)
                elif isinstance(gs, dict) and gs.get("propertyName"):
                    sum_type = gs.get("type", "Count")
                    self.group_summaries.append(GroupSummary(type=sum_type, property_name=gs.get("propertyName")))

