"""Product database module for LSCSIM."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

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

if TYPE_CHECKING:
    from pytola_sim.lscsim.interfaces.imainctrl import IMainCtrl


logger = get_logger(__name__)


class ProductDatabaseComponent(IComponent):
    """Product database component implementing IComponent interface."""

    def __init__(self) -> None:
        self._main_ctrl: IMainCtrl | None = None
        self._component_id = "ProductDatabase"
        self._is_initialized = False
        self._products: list[dict[str, Any]] = []
        logger.info("ProductDatabaseComponent 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_products()
            self._is_initialized = True

    def release(self) -> None:
        """Release component resources."""
        logger.info(f"Releasing {self._component_id}")
        self._products.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 "IProductDBCommands"
        return ""

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

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

        command_handlers = {
            "ProductDB.LoadProducts": self._load_products,
            "ProductDB.SaveProducts": self._save_products,
            "ProductDB.AddProduct": self._add_product,
            "ProductDB.UpdateProduct": self._update_product,
            "ProductDB.DeleteProduct": self._delete_product,
            "ProductDB.SearchProducts": self._search_products,
            "ProductDB.GetProductStructure": self._get_product_structure,
            "ProductDB.ExportProductData": self._export_product_data,
        }

        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

    def _load_products(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Load products from database."""
        logger.info("Loading products from database")
        # Implementation for loading products
        if isinstance(out_param, dict):
            out_param["products"] = self._products.copy()
        return True

    def _save_products(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Save products to database."""
        logger.info("Saving products to database")
        # Implementation for saving products
        return True

    def _add_product(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Add new product."""
        product_data = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Adding product: {product_data.get('name', 'Unknown')}")

        # Add product to internal list
        product_data.setdefault("id", len(self._products) + 1)
        self._products.append(product_data)
        return True

    def _update_product(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Update existing product."""
        product_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 product ID: {product_id}")

        # Find and update product
        for i, product in enumerate(self._products):
            if product.get("id") == product_id:
                self._products[i].update(update_data)
                return True
        return False

    def _delete_product(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Delete product."""
        product_id = in_param if not isinstance(in_param, dict) else in_param.get("id")
        logger.info(f"Deleting product ID: {product_id}")

        # Remove product from list
        self._products = [p for p in self._products if p.get("id") != product_id]
        return True

    def _search_products(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Search products by criteria."""
        search_criteria = in_param if isinstance(in_param, dict) else {}
        logger.info(f"Searching products with criteria: {search_criteria}")

        # Simple search implementation
        results = []
        for product in self._products:
            match = True
            for key, value in search_criteria.items():
                if key in product and str(product[key]).lower().find(str(value).lower()) == -1:
                    match = False
                    break
            if match:
                results.append(product)

        if isinstance(out_param, dict):
            out_param["results"] = results
        return True

    def _get_product_structure(self, in_param: Any, out_param: Any) -> bool:  # noqa: ANN401
        """Get product structure hierarchy."""
        logger.info("Getting product structure")
        # Implementation for product structure
        if isinstance(out_param, dict):
            out_param["structure"] = self._build_product_tree()
        return True

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

    def _load_sample_products(self) -> None:
        """Load sample products for demonstration."""
        sample_products = [
            {
                "id": 1,
                "name": "防护装甲板",
                "code": "ARMOR-001",
                "category": "防护装备",
                "description": "标准军用防护装甲板",
                "specifications": {
                    "厚度": "20mm",
                    "材质": "特种钢",
                    "重量": "15.5kg/m²",
                },
                "status": "active",
            },
            {
                "id": 2,
                "name": "防爆门窗",
                "code": "BLAST-002",
                "category": "建筑防护",
                "description": "防爆安全门窗系统",
                "specifications": {
                    "抗爆等级": "Level 3",
                    "尺寸": "2000x1000mm",
                    "材质": "钢化玻璃+钢材",
                },
                "status": "active",
            },
        ]
        self._products.extend(sample_products)
        logger.info(f"Loaded {len(sample_products)} sample products")

    def _build_product_tree(self) -> dict[str, Any]:
        """Build product hierarchy tree."""
        # Group products by category
        categories: dict[str, list[dict[str, Any]]] = {}
        for product in self._products:
            category = product.get("category", "未分类")
            if category not in categories:
                categories[category] = []
            categories[category].append(product)

        return {
            "name": "产品库",
            "type": "root",
            "children": [
                {"name": category, "type": "category", "children": products}
                for category, products in categories.items()
            ],
        }
