"""Job Statistics."""

from datetime import datetime
from enum import Enum

from msgspec import Struct, field

from slices_clientlib_aiis.util.msgspec import AwareDatetime


class ContainerUsageStatistics(Struct, rename="camel"):
    """Container Usage Statistics."""

    first_time: datetime
    last_time: datetime
    agg_period_ns: int
    cpu_count: int
    cpu_usage: float  # in nr CPU's, so between 0 and cpu_count
    cpu_usage_total_ns: int
    cpu_usage_kernelmode_ns: int
    cpu_usage_usermode_ns: int
    max_pid_count: int
    mem_limit_byte: int
    mem_usage_byte: int
    mem_max_usage_byte: int
    network_rx_byte: int
    network_tx_byte: int
    host_total_mWh_used: int | None = field(name="hostTotalmWhUsed", default=None)
    host_average_mW_used: int | None = field(name="hostAveragemWUsed", default=None)
    cpu_total_mWh_used: int | None = field(name="cpuTotalmWhUsed", default=None)
    cpu_average_mW_used: int | None = field(name="cpuAveragemWUsed", default=None)

    total_mWh_used: int | None = field(name="totalmWhUsed", default=None)
    average_mW_used: float | None = field(name="averagemWUsed", default=None)


class GpuUsageStatistics(Struct, rename="camel"):
    """GPU Usage Statistics."""

    gpu_count: int
    average_utilization: float
    average_mem_utilization: float
    total_mWh_used: int | None = field(name="totalmWhUsed", default=None)
    average_mW_used: int | None = field(name="averagemWUsed", default=None)


class WasteVerdict(Enum):
    """Waste Verdict."""

    GOOD = "Good"
    """Job is not wasting resources (yet, for running jobs)"""
    UNCERTAIN = "Uncertain"
    """Job might be wasting resources, or might not"""
    WASTE = "Waste"
    """Job is wasting resources"""
    SHORT = "Short"
    """Job was too short to verdict. It's OK if short test/failed jobs waste resources."""
    UNDECIDED = "Undecided"
    """Too soon to tell if job wastes resources"""

    @classmethod
    def _missing_(cls, value):
        """Handle missing enum values by ignoring case."""
        if isinstance(value, cls):
            return value
        if not isinstance(value, str):
            return None
        for member in cls:
            if member.name.lower() == value.lower():
                return member
            if member.value.lower() == value.lower():
                return member
        return None


class WasteFlag(Enum):
    """Waste Flag."""

    RED = "Red Flag"
    """Certainly unacceptable resource waste"""
    ORANGE = "Orange Flag"
    """Quite likely unacceptable resource waste"""
    YELLOW = "Yellow Flag"
    """Resource waste, but probably not unacceptable"""

    @classmethod
    def _missing_(cls, value):
        """Handle missing enum values by ignoring case."""
        if isinstance(value, cls):
            return value
        if not isinstance(value, str):
            return None
        for member in cls:
            if member.name.lower() == value.lower():
                return member
            if member.value.lower() == value.lower():
                return member
        return None


class WasteFlagInfo(Struct, rename="camel"):
    """Waste Flag Info."""

    flag: WasteFlag
    explanation: str


class WasteReview(Struct, rename="camel"):
    """Waste Review."""

    updated: AwareDatetime
    final: bool
    """This is the final report, as the job has finished. It can include details intermediate reports don't."""
    verdict: WasteVerdict
    """Is this job wasting resources, or not?"""
    flags: list[WasteFlagInfo] = []
    """Why is this job wasting resources? (empty if not wasting)"""
    debug: dict[str, bool | int | float | str] = {}


class GPULabUsageStatistics(Struct, rename="camel"):
    """GPULab Usage Statistics."""

    container_statistics: ContainerUsageStatistics
    gpu_statistics: GpuUsageStatistics

    # Power measurements
    #    (None if not (yet) available/implemented)
    #    (and for backward compatibility default is 0.0)

    total_mWh_used: int | None = field(name="totalmWhUsed", default=None)
    average_mW_used: float | None = field(name="averagemWUsed", default=None)
