"""Device management for Heiman Connect library.

Provides comprehensive device management features:
- Device filtering (include/exclude by room, type, model)
- Area name synchronization strategies
- Device display options
"""

from __future__ import annotations

import logging
from typing import Any, TYPE_CHECKING

if TYPE_CHECKING:
    from .models import HeimanDevice

_LOGGER = logging.getLogger(__name__)


class DeviceFilterManager:
    """Manages device filtering rules."""

    def __init__(self) -> None:
        """Initialize device filter manager."""
        self._filter_mode: str = "exclude"  # or "include"
        self._statistics_logic: str = "or"  # "and" or "or"
        self._room_filter_mode: str = "exclude"
        self._type_filter_mode: str = "exclude"
        self._model_filter_mode: str = "exclude"
        self._device_filter_mode: str = "exclude"

        # Filter lists
        self._room_list: set[str] = set()
        self._type_list: set[str] = set()
        self._model_list: set[str] = set()
        self._device_list: set[str] = set()

    def configure_filter(
        self,
        filter_mode: str = "exclude",
        statistics_logic: str = "or",
        room_filter_mode: str | None = None,
        room_list: list[str] | None = None,
        type_filter_mode: str | None = None,
        type_list: list[str] | None = None,
        model_filter_mode: str | None = None,
        model_list: list[str] | None = None,
        device_filter_mode: str | None = None,
        device_list: list[str] | None = None,
    ) -> None:
        """Configure device filter rules.

        Args:
            filter_mode: Global filter mode ("include" or "exclude")
            statistics_logic: Logic for combining filters ("and" or "or")
            room_filter_mode: Room filter mode
            room_list: List of rooms to filter
            type_filter_mode: Type filter mode
            type_list: List of device types to filter
            model_filter_mode: Model filter mode
            model_list: List of models to filter
            device_filter_mode: Device filter mode
            device_list: List of device IDs to filter
        """
        self._filter_mode = filter_mode
        self._statistics_logic = statistics_logic

        if room_filter_mode is not None:
            self._room_filter_mode = room_filter_mode
        if room_list:
            self._room_list = set(room_list)

        if type_filter_mode is not None:
            self._type_filter_mode = type_filter_mode
        if type_list:
            self._type_list = set(type_list)

        if model_filter_mode is not None:
            self._model_filter_mode = model_filter_mode
        if model_list:
            self._model_list = set(model_list)

        if device_filter_mode is not None:
            self._device_filter_mode = device_filter_mode
        if device_list:
            self._device_list = set(device_list)

        _LOGGER.info(
            "Device filter configured: mode=%s, logic=%s, rooms=%d, types=%d, models=%d, devices=%d",
            self._filter_mode,
            self._statistics_logic,
            len(self._room_list),
            len(self._type_list),
            len(self._model_list),
            len(self._device_list),
        )

    def should_include_device(self, device_info: dict[str, Any] | "HeimanDevice") -> bool:
        """Check if a device should be included based on filter rules.

        Args:
            device_info: Device information dictionary or HeimanDevice object

        Returns:
            True if device should be included, False otherwise
        """
        # Handle both dict and HeimanDevice objects
        if hasattr(device_info, "device_id"):
            # It's a HeimanDevice object
            device_id = device_info.device_id
            device_type = device_info.device_type or ""
            model = device_info.model or ""
            room_name = device_info.room_id or ""
        else:
            # It's a dict
            device_id = device_info.get("id") or device_info.get("deviceId", "")
            device_type = device_info.get("deviceType", "")
            model = device_info.get("model", "")
            room_name = device_info.get("roomName", "")

        # Collect which filters match
        matches = []

        # Check room filter
        if self._room_list:
            room_match = room_name in self._room_list
            if self._room_filter_mode == "include":
                matches.append(room_match)
            else:  # exclude
                matches.append(not room_match)

        # Check type filter
        if self._type_list:
            type_match = device_type in self._type_list
            if self._type_filter_mode == "include":
                matches.append(type_match)
            else:  # exclude
                matches.append(not type_match)

        # Check model filter
        if self._model_list:
            model_match = model in self._model_list
            if self._model_filter_mode == "include":
                matches.append(model_match)
            else:  # exclude
                matches.append(not model_match)

        # Check device filter
        if self._device_list:
            device_match = device_id in self._device_list
            if self._device_filter_mode == "include":
                matches.append(device_match)
            else:  # exclude
                matches.append(not device_match)

        # If no filters applied, include all
        if not matches:
            return True

        # Apply statistics logic
        if self._statistics_logic == "and":
            return all(matches)
        # "or"
        return any(matches)

    def get_filtered_devices(
        self, devices: list[dict[str, Any] | "HeimanDevice"]
    ) -> list[dict[str, Any] | "HeimanDevice"]:
        """Filter device list based on rules.

        Args:
            devices: List of device dictionaries or HeimanDevice objects

        Returns:
            Filtered list of devices
        """
        filtered = []
        for device in devices:
            if self.should_include_device(device):
                filtered.append(device)
            else:
                # Get device name and id for logging
                if hasattr(device, "device_name"):
                    device_name = device.device_name or "Unknown"
                    device_id = device.device_id
                else:
                    device_name = device.get("deviceName", "Unknown")
                    device_id = device.get("id", "")
                
                _LOGGER.debug(
                    "Filtered out device: %s (%s)",
                    device_name,
                    device_id,
                )

        _LOGGER.info("Device filter: %d/%d devices passed", len(filtered), len(devices))
        return filtered

    def clear_filters(self) -> None:
        """Clear all filter rules."""
        self._room_list.clear()
        self._type_list.clear()
        self._model_list.clear()
        self._device_list.clear()
        _LOGGER.info("All device filters cleared")

    @property
    def has_active_filters(self) -> bool:
        """Return whether any filter list is active."""
        return bool(
            self._room_list or self._type_list or self._model_list or self._device_list,
        )


class AreaNameSyncManager:
    """Manages area name synchronization strategies."""

    # Supported synchronization modes
    MODE_NONE = "none"
    MODE_ROOM = "room"
    MODE_HOME = "home"
    MODE_HOME_ROOM = "home_room"

    def __init__(self, mode: str = MODE_NONE) -> None:
        """Initialize area name sync manager.

        Args:
            mode: Synchronization mode
        """
        self._mode = mode

    def set_mode(self, mode: str) -> None:
        """Set synchronization mode.

        Args:
            mode: New mode
        """
        self._mode = mode
        _LOGGER.info("Area name sync mode set to: %s", mode)

    def get_mode(self) -> str:
        """Get current synchronization mode.

        Returns:
            Current mode
        """
        return self._mode

    def generate_area_name(
        self,
        home_name: str | None = None,
        room_name: str | None = None,
    ) -> str | None:
        """Generate area name based on sync mode.

        Args:
            home_name: Home name
            room_name: Room name

        Returns:
            Generated area name or None
        """
        if self._mode == self.MODE_NONE:
            return None

        if self._mode == self.MODE_ROOM:
            return room_name

        if self._mode == self.MODE_HOME:
            return home_name

        if self._mode == self.MODE_HOME_ROOM:
            if home_name and room_name:
                return f"{home_name} - {room_name}"
            if home_name:
                return home_name
            if room_name:
                return room_name

        return None

    def get_available_modes(self) -> dict[str, str]:
        """Get all available synchronization modes.

        Returns:
            Dictionary of mode -> description
        """
        return {
            self.MODE_NONE: "No sync",
            self.MODE_ROOM: "Room name",
            self.MODE_HOME: "Home name",
            self.MODE_HOME_ROOM: "Home name + Room name",
        }


class DeviceManagement:
    """Main device management class combining all managers."""

    def __init__(self) -> None:
        """Initialize device management."""
        self._filter_manager = DeviceFilterManager()
        self._area_sync_manager = AreaNameSyncManager()

    def configure(
        self,
        filter_config: dict[str, Any] | None = None,
        area_sync_mode: str | None = None,
    ) -> None:
        """Configure device management.

        Args:
            filter_config: Device filter configuration
            area_sync_mode: Area name synchronization mode
        """
        if filter_config:
            self._filter_manager.configure_filter(**filter_config)

        if area_sync_mode:
            self._area_sync_manager.set_mode(area_sync_mode)

        _LOGGER.info("Device management configured")

    @property
    def filter_manager(self) -> DeviceFilterManager:
        """Get filter manager instance."""
        return self._filter_manager

    @property
    def area_sync_manager(self) -> AreaNameSyncManager:
        """Get area sync manager instance."""
        return self._area_sync_manager

    def get_status(self) -> dict[str, Any]:
        """Get device management status.

        Returns:
            Status dictionary
        """
        return {
            "filter_active": self._filter_manager.has_active_filters,
            "area_sync_mode": self._area_sync_manager.get_mode(),
        }
