"""
Knowledge Graph Models for Breakpilot Agents

Entity and relationship data classes, plus type enumerations.
"""

from typing import Dict, Any
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum


class EntityType(Enum):
    """Types of entities in the knowledge graph"""
    STUDENT = "student"
    TEACHER = "teacher"
    CLASS = "class"
    SUBJECT = "subject"
    ASSIGNMENT = "assignment"
    EXAM = "exam"
    TOPIC = "topic"
    CONCEPT = "concept"
    RESOURCE = "resource"
    CUSTOM = "custom"


class RelationshipType(Enum):
    """Types of relationships between entities"""
    BELONGS_TO = "belongs_to"        # Student belongs to class
    TEACHES = "teaches"              # Teacher teaches subject
    ASSIGNED_TO = "assigned_to"      # Assignment assigned to student
    COVERS = "covers"                # Exam covers topic
    REQUIRES = "requires"            # Topic requires concept
    RELATED_TO = "related_to"        # General relationship
    PARENT_OF = "parent_of"          # Hierarchical relationship
    CREATED_BY = "created_by"        # Creator relationship
    GRADED_BY = "graded_by"          # Grading relationship


@dataclass
class Entity:
    """Represents an entity in the knowledge graph"""
    id: str
    entity_type: EntityType
    name: str
    properties: Dict[str, Any] = field(default_factory=dict)
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

    def to_dict(self) -> Dict[str, Any]:
        return {
            "id": self.id,
            "entity_type": self.entity_type.value,
            "name": self.name,
            "properties": self.properties,
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat()
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Entity":
        return cls(
            id=data["id"],
            entity_type=EntityType(data["entity_type"]),
            name=data["name"],
            properties=data.get("properties", {}),
            created_at=datetime.fromisoformat(data["created_at"]),
            updated_at=datetime.fromisoformat(data["updated_at"])
        )


@dataclass
class Relationship:
    """Represents a relationship between two entities"""
    id: str
    source_id: str
    target_id: str
    relationship_type: RelationshipType
    properties: Dict[str, Any] = field(default_factory=dict)
    weight: float = 1.0
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

    def to_dict(self) -> Dict[str, Any]:
        return {
            "id": self.id,
            "source_id": self.source_id,
            "target_id": self.target_id,
            "relationship_type": self.relationship_type.value,
            "properties": self.properties,
            "weight": self.weight,
            "created_at": self.created_at.isoformat()
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Relationship":
        return cls(
            id=data["id"],
            source_id=data["source_id"],
            target_id=data["target_id"],
            relationship_type=RelationshipType(data["relationship_type"]),
            properties=data.get("properties", {}),
            weight=data.get("weight", 1.0),
            created_at=datetime.fromisoformat(data["created_at"])
        )
