"""Simulation Database Component Module."""

from __future__ import annotations

from typing import Any, Dict, Union

from pytola_sim.lscsim.interfaces.icomponent import IComponent
from pytola_sim.lscsim.interfaces.imainctrl import IMainCtrl
from pytola_sim.lscsim.utils.logger import get_logger

logger = get_logger(__name__)

# Type alias for command parameters
ParamType = Union[Dict[str, Any], str, int, float, bool, None]


class SimulationDatabaseComponent(IComponent):
    """Simulation database component implementing IComponent interface."""

    def __init__(self) -> None:
        self._main_ctrl: IMainCtrl | None = None
        self._component_id = "SimulationDatabase"
        self._is_initialized = False
        self._materials: list[dict[str, Any]] = []
        self._target_plates: list[dict[str, Any]] = []
        self._templates: list[dict[str, Any]] = []
        logger.info("SimulationDatabaseComponent created")

    def get_id(self) -> str:
        """Get component ID."""
        return self._component_id

    def set_main_ctrl(self, main_ctrl: IMainCtrl) -> None:
        """Set main controller reference."""
        self._main_ctrl = main_ctrl
        logger.debug(f"Main controller set for {self._component_id}")

    def init(self) -> None:
        """Initialize component."""
        if not self._is_initialized:
            logger.info(f"Initializing {self._component_id}")
            self._load_sample_data()
            self._is_initialized = True

    def release(self) -> None:
        """Release component resources."""
        logger.info(f"Releasing {self._component_id}")
        self._materials.clear()
        self._target_plates.clear()
        self._templates.clear()
        self._is_initialized = False

    def get_interface_count(self) -> int:
        """Get number of interfaces provided by this component."""
        return 1

    def get_interface_id(self, index: int) -> str:
        """Get interface ID by index."""
        if index == 0:
            return "ISimDBCommands"
        return ""

    def get_interface_ptr(self, interface_id: str) -> object | None:
        """Get interface pointer by ID."""
        if interface_id == "ISimDBCommands":
            return self
        return None

    def execute_command(
        self,
        command_id: str,
        in_param: ParamType = None,
        out_param: ParamType = None,
    ) -> bool:
        """Execute simulation database command."""
        logger.debug(f"Executing command: {command_id}")

        command_handlers = {
            "SimDB.LoadMaterials": self._load_materials,
            "SimDB.AddMaterial": self._add_material,
            "SimDB.UpdateMaterial": self._update_material,
            "SimDB.DeleteMaterial": self._delete_material,
            "SimDB.SearchMaterials": self._search_materials,
            "SimDB.LoadTargetPlates": self._load_target_plates,
            "SimDB.AddTargetPlate": self._add_target_plate,
            "SimDB.UpdateTargetPlate": self._update_target_plate,
            "SimDB.DeleteTargetPlate": self._delete_target_plate,
            "SimDB.SearchTargetPlates": self._search_target_plates,
            "SimDB.LoadTemplates": self._load_templates,
            "SimDB.AddTemplate": self._add_template,
            "SimDB.UpdateTemplate": self._update_template,
            "SimDB.DeleteTemplate": self._delete_template,
            "SimDB.SearchTemplates": self._search_templates,
            "SimDB.ExportLibrary": self._export_library,
        }

        handler = command_handlers.get(command_id)
        if handler:
            try:
                result = handler(in_param, out_param)
                logger.info(f"Command {command_id} executed successfully")
            except (RuntimeError, ValueError, OSError):
                logger.exception(f"Command {command_id} failed")
                return False
        else:
            logger.warning(f"Unknown command: {command_id}")
            return False
        return result

    # Material operations
    def _load_materials(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Load materials from database."""
        logger.info("Loading materials from database")
        if isinstance(out_param, dict):
            out_param["materials"] = self._materials.copy()
        return True

    def _add_material(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Add new material."""
        material_data = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Adding material: {material_data.get('name', 'Unknown')}")

        material_data.setdefault("id", len(self._materials) + 1)
        self._materials.append(material_data)
        return True

    def _update_material(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Update existing material."""
        material_id = in_param.get("id") if isinstance(in_param, dict) else None
        update_data = in_param.get("data", {}) if isinstance(in_param, dict) else {}

        logger.info(f"Updating material ID: {material_id}")

        for i, material in enumerate(self._materials):
            if material.get("id") == material_id:
                self._materials[i].update(update_data)
                return True
        return False

    def _delete_material(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Delete material."""
        material_id = in_param if not isinstance(in_param, dict) else in_param.get("id")
        logger.info(f"Deleting material ID: {material_id}")

        self._materials = [m for m in self._materials if m.get("id") != material_id]
        return True

    def _search_materials(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Search materials by criteria."""
        search_criteria = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Searching materials with criteria: {search_criteria}")

        results = self._search_items(self._materials, search_criteria)
        if isinstance(out_param, dict):
            out_param["results"] = results
        return True

    # Target plate operations
    def _load_target_plates(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Load target plates from database."""
        logger.info("Loading target plates from database")
        if isinstance(out_param, dict):
            out_param["target_plates"] = self._target_plates.copy()
        return True

    def _add_target_plate(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Add new target plate."""
        plate_data = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Adding target plate: {plate_data.get('name', 'Unknown')}")

        plate_data.setdefault("id", len(self._target_plates) + 1)
        self._target_plates.append(plate_data)
        return True

    def _update_target_plate(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Update existing target plate."""
        plate_id = in_param.get("id") if isinstance(in_param, dict) else None
        update_data = in_param.get("data", {}) if isinstance(in_param, dict) else {}

        logger.info(f"Updating target plate ID: {plate_id}")

        for i, plate in enumerate(self._target_plates):
            if plate.get("id") == plate_id:
                self._target_plates[i].update(update_data)
                return True
        return False

    def _delete_target_plate(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Delete target plate."""
        plate_id = in_param if not isinstance(in_param, dict) else in_param.get("id")
        logger.info(f"Deleting target plate ID: {plate_id}")

        self._target_plates = [p for p in self._target_plates if p.get("id") != plate_id]
        return True

    def _search_target_plates(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Search target plates by criteria."""
        search_criteria = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Searching target plates with criteria: {search_criteria}")

        results = self._search_items(self._target_plates, search_criteria)
        if isinstance(out_param, dict):
            out_param["results"] = results
        return True

    # Template operations
    def _load_templates(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Load templates from database."""
        logger.info("Loading templates from database")
        if isinstance(out_param, dict):
            out_param["templates"] = self._templates.copy()
        return True

    def _add_template(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Add new template."""
        template_data = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Adding template: {template_data.get('name', 'Unknown')}")

        template_data.setdefault("id", len(self._templates) + 1)
        self._templates.append(template_data)
        return True

    def _update_template(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Update existing template."""
        template_id = in_param.get("id") if isinstance(in_param, dict) else None
        update_data = in_param.get("data", {}) if isinstance(in_param, dict) else {}

        logger.info(f"Updating template ID: {template_id}")

        for i, template in enumerate(self._templates):
            if template.get("id") == template_id:
                self._templates[i].update(update_data)
                return True
        return False

    def _delete_template(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Delete template."""
        template_id = in_param if not isinstance(in_param, dict) else in_param.get("id")
        logger.info(f"Deleting template ID: {template_id}")

        self._templates = [t for t in self._templates if t.get("id") != template_id]
        return True

    def _search_templates(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Search templates by criteria."""
        search_criteria = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Searching templates with criteria: {search_criteria}")

        results = self._search_items(self._templates, search_criteria)
        if isinstance(out_param, dict):
            out_param["results"] = results
        return True

    def _export_library(self, in_param: ParamType, out_param: ParamType) -> bool:
        """Export simulation library data."""
        export_format = in_param.get("format", "json") if isinstance(in_param, dict) else "json"
        logger.info(f"Exporting simulation library in {export_format} format")
        # Implementation for library export
        return True

    def _search_items(
        self,
        items: list[dict[str, Any]],
        criteria: dict[str, Any],
    ) -> list[dict[str, Any]]:
        results = []
        for item in items:
            match = True
            for key, value in criteria.items():
                if key in item and str(item[key]).lower().find(str(value).lower()) == -1:
                    match = False
                    break
            if match:
                results.append(item)
        return results

    def _load_sample_data(self) -> None:
        """Load sample simulation data for demonstration."""
        # Sample materials
        sample_materials = [
            {
                "id": 1,
                "name": "结构钢",
                "category": "金属材料",
                "density": 7850,
                "young_modulus": 200e9,
                "poisson_ratio": 0.3,
                "yield_strength": 250e6,
                "description": "标准结构钢材料",
            },
            {
                "id": 2,
                "name": "铝合金",
                "category": "金属材料",
                "density": 2700,
                "young_modulus": 70e9,
                "poisson_ratio": 0.33,
                "yield_strength": 276e6,
                "description": "轻质高强度铝合金",
            },
        ]

        # Sample target plates
        sample_plates = [
            {
                "id": 1,
                "name": "标准装甲板",
                "type": "装甲防护",
                "thickness": 20,
                "material": "结构钢",
                "dimensions": "1000x500mm",
                "description": "标准军用装甲防护板",
            },
            {
                "id": 2,
                "name": "复合装甲",
                "type": "装甲防护",
                "thickness": 30,
                "material": "陶瓷+金属",
                "dimensions": "1200x600mm",
                "description": "先进复合装甲结构",
            },
        ]

        # Sample templates
        sample_templates = [
            {
                "id": 1,
                "name": "静态结构分析",
                "category": "结构分析",
                "analysis_type": "static",
                "solver": "implicit",
                "description": "标准静态结构分析模板",
            },
            {
                "id": 2,
                "name": "冲击动力分析",
                "category": "动力分析",
                "analysis_type": "dynamic",
                "solver": "explicit",
                "description": "显式动力冲击分析模板",
            },
        ]

        self._materials.extend(sample_materials)
        self._target_plates.extend(sample_plates)
        self._templates.extend(sample_templates)

        logger.info(
            f"Loaded sample data: {len(sample_materials)} materials, "
            f"{len(sample_plates)} plates, {len(sample_templates)} templates",
        )
