"""REST Operations für Audit-Endpoints."""

from __future__ import annotations

from collections.abc import Callable
from datetime import datetime

from loguru import logger

from ..models.rest import (
    TimeSeriesData,
    TimeSeriesDataPayload,
    TimeSeriesPayload,
)
from ..models.timeseries import (
    Aggregation,
    Interval,
    Quality,
    QuotationBehavior,
    TimeSeriesValue,
    TimeUnit,
    ValueAlignment,
    ValueAvailability,
)


class AuditOperations:
    """
    REST-Operationen für Audit-Endpoints.

    Bietet Methoden zum Abrufen von Audit-Daten für Dateien und Zeitreihen.
    """

    def __init__(self, rest_get_func: Callable):
        """
        Initialisiert die Audit-Operationen.

        Args:
            rest_get_func: Funktion für GET-Requests
        """
        self._get = rest_get_func
        logger.debug("AuditOperations initialized")

    def get_file(self, file_id: int) -> bytes:
        """
        Ruft Audit-Daten für eine Datei ab.

        Args:
            file_id: ID der Datei

        Returns:
            bytes: Dateiinhalt als Bytes
        """
        logger.info(f"Getting audit data for file {file_id}")
        result = self._get("/audit/file", params={"fileId": file_id})
        logger.info(f"Audit file data retrieved, size: {len(result)} bytes")
        return result

    def get_timeseries(self, time_series_id: int) -> TimeSeriesPayload:
        """
        Ruft Audit-Metadaten für eine TimeSeries ab.

        Args:
            time_series_id: ID der TimeSeries

        Returns:
            TimeSeriesPayload: Objekt mit Metadaten
        """
        logger.info(f"Getting audit metadata for timeseries {time_series_id}")
        result = self._get("/audit/timeseries", params={"timeSeriesId": time_series_id})

        # Parse Response
        interval_data = result.get("interval", {})
        interval = Interval(
            time_unit=TimeUnit(interval_data.get("timeUnit")),
            multiplier=interval_data.get("multiplier", 1),
        )

        timeseries = TimeSeriesPayload(
            id=result["id"],
            created_by=result["createdBy"],
            created_at=datetime.fromisoformat(
                result["createdAt"].replace("Z", "+00:00")
            ),
            altered_by=result["alteredBy"],
            altered_at=datetime.fromisoformat(
                result["alteredAt"].replace("Z", "+00:00")
            ),
            interval=interval,
            value_alignment=ValueAlignment(result["valueAlignment"]),
            value_availability=ValueAvailability(result["valueAvailability"]),
            unit=result.get("unit"),
            time_zone=result.get("timeZone"),
            default_aggregation=Aggregation(result["defaultAggregation"]),
            start_of_time=datetime.fromisoformat(
                result["startOfTime"].replace("Z", "+00:00")
            ),
            audit_enabled=result["auditEnabled"],
            quotation_enabled=result["quotationEnabled"],
            default_quotation_behavior=QuotationBehavior(
                result["defaultQuotationBehavior"]
            ),
        )

        logger.info("Timeseries audit metadata retrieved successfully")
        return timeseries

    def get_timeseries_data(
        self,
        time_series_id: int,
        from_time: datetime,
        to_time: datetime,
        audit_time: datetime,
        audit_exactly_at: bool = False,
        quotation_time: datetime | None = None,
        quotation_exactly_at: bool = False,
        quotation_behavior: QuotationBehavior | None = None,
        exclude_qualities: list[Quality] | None = None,
    ) -> TimeSeriesDataPayload:
        """
        Ruft Audit-Daten für eine TimeSeries ab.

        Args:
            time_series_id: ID der TimeSeries
            from_time: Start des Zeitbereichs
            to_time: Ende des Zeitbereichs
            audit_time: Audit-Zeitpunkt
            audit_exactly_at: Exakt am Audit-Zeitpunkt (default: False = vor Zeitpunkt)
            quotation_time: Quotierungs-Zeitpunkt (optional)
            quotation_exactly_at: Exakt am Quotierungs-Zeitpunkt (default: False)
            quotation_behavior: Quotierungs-Verhalten (optional)
            exclude_qualities: Auszuschließende Qualitäten (optional)

        Returns:
            TimeSeriesDataPayload: Objekt mit Audit-Daten
        """
        logger.info(
            "Getting audit data for timeseries",
            time_series_id=time_series_id,
            from_time=from_time,
            to_time=to_time,
            audit_time=audit_time,
        )

        params = {
            "timeSeriesId": time_series_id,
            "from": from_time.isoformat(),
            "to": to_time.isoformat(),
            "auditTime": audit_time.isoformat(),
            "auditExactlyAt": audit_exactly_at,
        }

        if quotation_time:
            params["quotationTime"] = quotation_time.isoformat()

        params["quotationExactlyAt"] = quotation_exactly_at

        if quotation_behavior:
            params["quotationBehavior"] = quotation_behavior.value

        if exclude_qualities:
            params["excludeQualities"] = [q.value for q in exclude_qualities]

        result = self._get("/audit/timeseries/data", params=params)

        # Parse Response (ähnlich wie bei get_data)
        data_list = []
        for ts_data in result.get("data", []):
            interval_data = ts_data.get("interval", {})
            interval = Interval(
                time_unit=TimeUnit(interval_data.get("timeUnit")),
                multiplier=interval_data.get("multiplier", 1),
            )

            values = []
            for val in ts_data.get("values", []):
                ts_value = TimeSeriesValue(
                    time=datetime.fromisoformat(val["time"].replace("Z", "+00:00")),
                    value=val["value"],
                    quality=Quality(val["quality"]) if val.get("quality") else None,
                )
                values.append(ts_value)

            ts_data_obj = TimeSeriesData(
                time_series_id=ts_data["timeSeriesId"],
                interval=interval,
                unit=ts_data.get("unit"),
                time_zone=ts_data.get("timeZone"),
                values=values,
            )
            data_list.append(ts_data_obj)

        logger.info("Timeseries audit data retrieved successfully")
        return TimeSeriesDataPayload(data=data_list)
