"""Execution Monitoring client for ZenOTC SDK."""

from __future__ import annotations

from datetime import datetime
from typing import Any, Dict, List, Optional

from zenotc.clients.base import BaseClient
from zenotc.models.monitoring import (
    DashboardData,
    ErrorPattern,
    ErrorSummary,
    ExecutionError,
    FillRateMetrics,
    FillSummary,
    LatencyPercentiles,
    OrderMonitoring,
    AlgoMonitoring,
    SlippageMetrics,
)


class MonitoringClient(BaseClient):
    """Client for execution monitoring operations."""

    async def get_dashboard(self) -> DashboardData:
        """Get the monitoring dashboard with real-time metrics.

        Returns:
            DashboardData with real-time metrics, alerts, and error patterns.
        """
        response = await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/dashboard",
        )
        return DashboardData(**response)

    async def get_order_monitoring(self, order_id: str) -> OrderMonitoring:
        """Get monitoring data for a specific order.

        Args:
            order_id: The order ID to get monitoring data for.

        Returns:
            OrderMonitoring with timeline, fills, latency, and errors.
        """
        response = await self._rate_limited_request(
            "GET",
            f"/sdk/monitoring/orders/{order_id}",
        )
        return OrderMonitoring(**response)

    async def get_algo_monitoring(self, algo_order_id: str) -> AlgoMonitoring:
        """Get monitoring data for an algo order.

        Args:
            algo_order_id: The algo order ID to get monitoring data for.

        Returns:
            AlgoMonitoring with timeline, fills, child orders, and progress.
        """
        response = await self._rate_limited_request(
            "GET",
            f"/sdk/monitoring/algos/{algo_order_id}",
        )
        return AlgoMonitoring(**response)

    async def get_fill_metrics(
        self,
        start_time: datetime,
        end_time: datetime,
    ) -> FillRateMetrics:
        """Get fill rate metrics for a time period.

        Args:
            start_time: Start of the period.
            end_time: End of the period.

        Returns:
            FillRateMetrics with fill rates and order counts.
        """
        response = await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/metrics/fills",
            params={
                "startTime": start_time.isoformat(),
                "endTime": end_time.isoformat(),
            },
        )
        return FillRateMetrics(**response)

    async def get_slippage_metrics(
        self,
        start_time: datetime,
        end_time: datetime,
    ) -> SlippageMetrics:
        """Get slippage metrics for a time period.

        Args:
            start_time: Start of the period.
            end_time: End of the period.

        Returns:
            SlippageMetrics with average, worst, and best slippage.
        """
        response = await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/metrics/slippage",
            params={
                "startTime": start_time.isoformat(),
                "endTime": end_time.isoformat(),
            },
        )
        return SlippageMetrics(**response)

    async def get_latency_metrics(
        self,
        start_time: datetime,
        end_time: datetime,
        venue: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Get latency metrics for a time period.

        Args:
            start_time: Start of the period.
            end_time: End of the period.
            venue: Optional venue to filter by.

        Returns:
            Dict with percentiles, by_venue, and by_phase breakdowns.
        """
        params = {
            "startTime": start_time.isoformat(),
            "endTime": end_time.isoformat(),
        }
        if venue:
            params["venue"] = venue

        return await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/metrics/latency",
            params=params,
        )

    async def get_venue_metrics(
        self,
        start_time: datetime,
        end_time: datetime,
    ) -> Dict[str, Dict[str, Any]]:
        """Get metrics breakdown by venue.

        Args:
            start_time: Start of the period.
            end_time: End of the period.

        Returns:
            Dict mapping venue names to their metrics.
        """
        return await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/metrics/venues",
            params={
                "startTime": start_time.isoformat(),
                "endTime": end_time.isoformat(),
            },
        )

    async def get_error_metrics(
        self,
        start_time: datetime,
        end_time: datetime,
    ) -> Dict[str, Any]:
        """Get error metrics and patterns.

        Args:
            start_time: Start of the period.
            end_time: End of the period.

        Returns:
            Dict with summary, patterns, and unresolved critical errors.
        """
        return await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/metrics/errors",
            params={
                "startTime": start_time.isoformat(),
                "endTime": end_time.isoformat(),
            },
        )

    async def get_unresolved_errors(self) -> List[ExecutionError]:
        """Get unresolved critical/high severity errors.

        Returns:
            List of unresolved ExecutionError objects.
        """
        response = await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/errors/unresolved",
        )
        return [ExecutionError(**e) for e in response]

    async def get_latency_percentiles(
        self,
        start_time: datetime,
        end_time: datetime,
        venue: Optional[str] = None,
    ) -> LatencyPercentiles:
        """Get latency percentile distribution.

        Args:
            start_time: Start of the period.
            end_time: End of the period.
            venue: Optional venue to filter by.

        Returns:
            LatencyPercentiles with min, max, avg, p50-p99.
        """
        params = {
            "startTime": start_time.isoformat(),
            "endTime": end_time.isoformat(),
        }
        if venue:
            params["venue"] = venue

        response = await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/latency/percentiles",
            params=params,
        )
        return LatencyPercentiles(**response)

    async def get_latency_by_venue(
        self,
        start_time: datetime,
        end_time: datetime,
    ) -> Dict[str, float]:
        """Get average latency by venue.

        Args:
            start_time: Start of the period.
            end_time: End of the period.

        Returns:
            Dict mapping venue names to average latency in ms.
        """
        return await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/latency/by-venue",
            params={
                "startTime": start_time.isoformat(),
                "endTime": end_time.isoformat(),
            },
        )

    async def get_latency_by_phase(
        self,
        start_time: datetime,
        end_time: datetime,
    ) -> Dict[str, float]:
        """Get average latency by execution phase.

        Args:
            start_time: Start of the period.
            end_time: End of the period.

        Returns:
            Dict mapping phase names to average latency in ms.
        """
        return await self._rate_limited_request(
            "GET",
            "/sdk/monitoring/latency/by-phase",
            params={
                "startTime": start_time.isoformat(),
                "endTime": end_time.isoformat(),
            },
        )

    async def get_order_fills(self, order_id: str) -> FillSummary:
        """Get fill summary for an order.

        Args:
            order_id: The order ID.

        Returns:
            FillSummary with total filled, notional, VWAP, etc.
        """
        response = await self._rate_limited_request(
            "GET",
            f"/sdk/monitoring/fills/summary/{order_id}",
        )
        return FillSummary(**response)

    async def get_algo_fills(self, algo_order_id: str) -> FillSummary:
        """Get fill summary for an algo order.

        Args:
            algo_order_id: The algo order ID.

        Returns:
            FillSummary with aggregated fills across all child orders.
        """
        response = await self._rate_limited_request(
            "GET",
            f"/sdk/monitoring/fills/algo/{algo_order_id}",
        )
        return FillSummary(**response)
