from dataclasses import dataclass, field
from enum import IntEnum, Enum
import time
from typing import Optional, Dict, Any


# -------------------------------
# Priority & State Enums
# -------------------------------

class IntentPriority(IntEnum):
    LOW = 3
    NORMAL = 2
    HIGH = 1
    CRITICAL = 0


class IntentCriticality(Enum):
    CRITICAL = "CRITICAL"
    NON_CRITICAL = "NON_CRITICAL"


class IntentState(Enum):
    PENDING = "PENDING"
    SCHEDULED = "SCHEDULED"
    EXECUTING = "EXECUTING"
    COMPLETED = "COMPLETED"
    PREEMPTED = "PREEMPTED"
    REJECTED = "REJECTED"
    EXPIRED = "EXPIRED"
    FAILED = "FAILED"


# -------------------------------
# Intent Domain Object
# -------------------------------

@dataclass
class Intent:
    intent_id: str
    name: str
    capability: str
    priority: IntentPriority
    criticality: IntentCriticality = IntentCriticality.NON_CRITICAL
    preemptible: bool = True

    created_at: float = field(default_factory=time.time)
    ttl: Optional[int] = None
    retry_count: int = 0
    max_retries: int = 3
    sla_timeout: Optional[float] = None
    metadata: Dict[str, Any] = field(default_factory=dict)

    def __init__(
        self,
        intent_id: str,
        name: str,
        capability: str,
        priority: IntentPriority = IntentPriority.NORMAL,
        criticality: IntentCriticality = IntentCriticality.NON_CRITICAL,
        preemptible: bool = True,
        ttl: Optional[int] = None,
        state: IntentState = IntentState.PENDING,
        retry_count: int = 0,
        max_retries: int = 3,
        sla_timeout: Optional[float] = None,
        metadata: Optional[Dict] = None
    ):
        self.intent_id = intent_id
        self.name = name
        self.capability = capability
        self.priority = priority
        self.criticality = criticality
        self.preemptible = preemptible
        self.ttl = ttl
        self.state = state
        self.retry_count = retry_count
        self.max_retries = max_retries
        self.sla_timeout = sla_timeout
        self.metadata = metadata or {}
        self.created_at = time.time()

        self.validate()

    # -------------------------------
    # Lifecycle Helpers
    # -------------------------------

    def validate(self) -> bool:
        if not self.name or not self.capability:
            return False

        if not isinstance(self.priority, IntentPriority):
            return False

        if not isinstance(self.criticality, IntentCriticality):
            return False

        return True


    def mark_executing(self):
        self.state = IntentState.EXECUTING

    def mark_preempted(self):
        self.state = IntentState.PREEMPTED

    def is_expired(self) -> bool:
        if self.ttl is None:
            return False
        return time.time() > self.created_at + self.ttl

    def is_sla_violated(self) -> bool:
        if self.sla_timeout is None:
            return False
        return time.time() > self.created_at + self.sla_timeout

    # -------------------------------
    # Persistence (CRITICAL)
    # -------------------------------

    def to_dict(self) -> dict:
        return {
            "intent_id": self.intent_id,
            "name": self.name,
            "capability": self.capability,
            "priority": int(self.priority),
            "criticality": self.criticality.value,
            "state": self.state.value,
            "preemptible": self.preemptible,
            "ttl": self.ttl,
            "retry_count": self.retry_count,
            "max_retries": self.max_retries,
            "sla_timeout": self.sla_timeout,
            "created_at": self.created_at,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "Intent":
        """Create Intent from dictionary"""
        # Handle priority (could be string or int)
        priority_val = data.get("priority", IntentPriority.NORMAL)
        if isinstance(priority_val, str):
            try:
                priority = IntentPriority[priority_val.upper()]
            except KeyError:
                # Fallback if string is not a valid enum name
                priority = IntentPriority.NORMAL
        else:
            try:
                priority = IntentPriority(priority_val)
            except ValueError:
                priority = IntentPriority.NORMAL

        # Handle State
        state_val = data.get("state", IntentState.SCHEDULED)
        if isinstance(state_val, str):
            try:
                state = IntentState(state_val)
            except ValueError:
                state = IntentState.SCHEDULED
        else:
            state = state_val

        # Handle Criticality
        crit_val = data.get("criticality", IntentCriticality.NON_CRITICAL)
        if isinstance(crit_val, str):
            try:
                criticality = IntentCriticality(crit_val.upper())
            except ValueError:
                criticality = IntentCriticality.NON_CRITICAL
        else:
            criticality = crit_val

        intent = cls(
            intent_id=data["intent_id"],
            name=data["name"],
            capability=data["capability"],
            priority=priority,
            criticality=criticality,
            preemptible=data.get("preemptible", True),
            ttl=data.get("ttl"),
            state=state,
            retry_count=data.get("retry_count", 0),
            max_retries=data.get("max_retries", 3),
            sla_timeout=data.get("sla_timeout"),
            metadata=data.get("metadata", {}),
        )
        intent.created_at = data.get("created_at", time.time())
        return intent

