"""Enhanced data models for LSCSIM data management."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from pathlib import Path
from typing import Any

from pytola_sim.lscsim.models.project_model import Material, SimulationTemplate


class DataType(Enum):
    """Types of data that can be managed."""

    PROJECT = "project"
    MATERIAL = "material"
    TEMPLATE = "template"
    RESULT = "result"
    CONFIGURATION = "configuration"


class DataStatus(Enum):
    """Status of data items."""

    ACTIVE = "active"
    ARCHIVED = "archived"
    DELETED = "deleted"
    DRAFT = "draft"


@dataclass
class DataMetadata:
    """Metadata for data items."""

    data_type: DataType
    name: str
    description: str = ""
    version: str = "1.0.0"
    created_date: datetime = field(default_factory=datetime.now)
    modified_date: datetime = field(default_factory=datetime.now)
    author: str = ""
    tags: list[str] = field(default_factory=list)
    status: DataStatus = DataStatus.ACTIVE
    size_bytes: int = 0
    file_path: Path | None = None

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "data_type": self.data_type.value,
            "name": self.name,
            "description": self.description,
            "version": self.version,
            "created_date": self.created_date.isoformat(),
            "modified_date": self.modified_date.isoformat(),
            "author": self.author,
            "tags": self.tags,
            "status": self.status.value,
            "size_bytes": self.size_bytes,
            "file_path": str(self.file_path) if self.file_path else None,
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> DataMetadata:
        """Create from dictionary."""
        return cls(
            data_type=DataType(data["data_type"]),
            name=data["name"],
            description=data.get("description", ""),
            version=data.get("version", "1.0.0"),
            created_date=datetime.fromisoformat(data["created_date"]),
            modified_date=datetime.fromisoformat(data["modified_date"]),
            author=data.get("author", ""),
            tags=data.get("tags", []),
            status=DataStatus(data.get("status", "active")),
            size_bytes=data.get("size_bytes", 0),
            file_path=Path(data["file_path"]) if data.get("file_path") else None,
        )


@dataclass
class MaterialLibrary:
    """Enhanced material library with categorization."""

    name: str
    description: str = ""
    materials: list[Material] = field(default_factory=list)
    categories: dict[str, list[str]] = field(
        default_factory=dict,
    )  # category -> material names
    created_date: datetime = field(default_factory=datetime.now)

    def add_material(self, material: Material, categories: list[str] | None = None) -> bool:
        """Add material to library."""
        # Check if material already exists
        if any(m.name == material.name for m in self.materials):
            return False

        self.materials.append(material)

        # Add to categories
        if categories:
            for category in categories:
                if category not in self.categories:
                    self.categories[category] = []
                self.categories[category].append(material.name)

        return True

    def get_material(self, name: str) -> Material | None:
        """Get material by name."""
        for material in self.materials:
            if material.name == name:
                return material
        return None

    def get_materials_by_category(self, category: str) -> list[Material]:
        """Get materials in a specific category."""
        if category not in self.categories:
            return []

        material_names = self.categories[category]
        return [m for m in self.materials if m.name in material_names]

    def get_categories(self) -> list[str]:
        """Get all categories."""
        return list(self.categories.keys())

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "name": self.name,
            "description": self.description,
            "materials": [m.to_dict() for m in self.materials],
            "categories": self.categories,
            "created_date": self.created_date.isoformat(),
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> MaterialLibrary:
        """Create from dictionary."""
        return cls(
            name=data["name"],
            description=data.get("description", ""),
            materials=[Material.from_dict(m) for m in data.get("materials", [])],
            categories=data.get("categories", {}),
            created_date=datetime.fromisoformat(data["created_date"]),
        )


@dataclass
class TemplateLibrary:
    """Enhanced template library with organization."""

    name: str
    description: str = ""
    templates: list[SimulationTemplate] = field(default_factory=list)
    categories: dict[str, list[str]] = field(default_factory=dict)
    created_date: datetime = field(default_factory=datetime.now)

    def add_template(
        self,
        template: SimulationTemplate,
        categories: list[str] | None = None,
    ) -> bool:
        """Add template to library."""
        # Check if template already exists
        if any(t.name == template.name for t in self.templates):
            return False

        self.templates.append(template)

        # Add to categories
        if categories:
            for category in categories:
                if category not in self.categories:
                    self.categories[category] = []
                self.categories[category].append(template.name)

        return True

    def get_template(self, name: str) -> SimulationTemplate | None:
        """Get template by name."""
        for template in self.templates:
            if template.name == name:
                return template
        return None

    def get_templates_by_category(self, category: str) -> list[SimulationTemplate]:
        """Get templates in a specific category."""
        if category not in self.categories:
            return []

        template_names = self.categories[category]
        return [t for t in self.templates if t.name in template_names]

    def get_categories(self) -> list[str]:
        """Get all categories."""
        return list(self.categories.keys())

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "name": self.name,
            "description": self.description,
            "templates": [t.to_dict() for t in self.templates],
            "categories": self.categories,
            "created_date": self.created_date.isoformat(),
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> TemplateLibrary:
        """Create from dictionary."""
        return cls(
            name=data["name"],
            description=data.get("description", ""),
            templates=[SimulationTemplate.from_dict(t) for t in data.get("templates", [])],
            categories=data.get("categories", {}),
            created_date=datetime.fromisoformat(data["created_date"]),
        )


@dataclass
class DataManagerConfig:
    """Configuration for data management system."""

    # Storage settings
    data_directory: Path = Path.home() / "LSCSIM_Data"
    max_recent_items: int = 50
    auto_backup_enabled: bool = True
    backup_interval_hours: int = 24

    # Validation settings
    validate_data_integrity: bool = True
    check_file_permissions: bool = True

    # Performance settings
    cache_enabled: bool = True
    max_cache_size_mb: int = 100
    compression_enabled: bool = True

    def __post_init__(self) -> None:
        """Initialize configuration."""
        self.data_directory.mkdir(parents=True, exist_ok=True)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "data_directory": str(self.data_directory),
            "max_recent_items": self.max_recent_items,
            "auto_backup_enabled": self.auto_backup_enabled,
            "backup_interval_hours": self.backup_interval_hours,
            "validate_data_integrity": self.validate_data_integrity,
            "check_file_permissions": self.check_file_permissions,
            "cache_enabled": self.cache_enabled,
            "max_cache_size_mb": self.max_cache_size_mb,
            "compression_enabled": self.compression_enabled,
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> DataManagerConfig:
        """Create from dictionary."""
        return cls(
            data_directory=Path(data["data_directory"]),
            max_recent_items=data.get("max_recent_items", 50),
            auto_backup_enabled=data.get("auto_backup_enabled", True),
            backup_interval_hours=data.get("backup_interval_hours", 24),
            validate_data_integrity=data.get("validate_data_integrity", True),
            check_file_permissions=data.get("check_file_permissions", True),
            cache_enabled=data.get("cache_enabled", True),
            max_cache_size_mb=data.get("max_cache_size_mb", 100),
            compression_enabled=data.get("compression_enabled", True),
        )
