"""HTTP client for Heiman Cloud API."""

import json
import logging
import re
from pathlib import Path
from typing import Any, Optional

import aiohttp

from .exceptions import HeimanApiError, HeimanAuthError, HeimanConnectionError
from .models import HeimanDevice, HeimanHome, HeimanUser

_LOGGER = logging.getLogger(__name__)

# Cache for product type translations
_PRODUCT_TYPE_CACHE: dict[str, str] = {}
_PRODUCT_TYPE_LOAD_ATTEMPTED = False


def _load_product_type_translations_sync(lang: str = "en") -> dict[str, str]:
    """Load product type translations from Heiman Home strings.json (sync version for executor).
    
    Args:
        lang: Language code (default: en)
        
    Returns:
        Dictionary mapping product_id to product name
    """
    try:
        # Load from Heiman Home integration's strings.json
        # This file is located at custom_components/heiman_home/strings.json
        module_dir = Path(__file__).parent.parent.parent / "heiman_home"
        strings_file = module_dir / "strings.json"
        
        if not strings_file.exists():
            _LOGGER.debug(f"strings.json not found at {strings_file}, using empty translations")
            return {}
        
        with open(strings_file, "r", encoding="utf-8") as f:
            strings_data = json.load(f)
        
        # Extract product_type mappings from strings.json
        product_types = strings_data.get("product_type", {})
        
        _LOGGER.debug(f"Loaded {len(product_types)} product type translations from {strings_file}")
        return product_types
        
    except FileNotFoundError:
        _LOGGER.debug(f"Translation file not found: {strings_file}")
        return {}
    except json.JSONDecodeError as err:
        _LOGGER.error(f"Failed to parse strings.json {strings_file}: {err}")
        return {}
    except Exception as err:
        _LOGGER.error(f"Failed to load product type translations: {err}")
        return {}


def _get_product_type_translations(lang: str = "en") -> dict[str, str]:
    """Get product type translations from Heiman Home strings.json (non-blocking version).
    
    This function loads translations synchronously on first call and caches them.
    For Home Assistant, this is acceptable as it's only called once during startup.
    
    Args:
        lang: Language code (default: en) - kept for compatibility but not used
        
    Returns:
        Dictionary mapping product_id to product name
    """
    global _PRODUCT_TYPE_CACHE, _PRODUCT_TYPE_LOAD_ATTEMPTED
    
    if _PRODUCT_TYPE_LOAD_ATTEMPTED and _PRODUCT_TYPE_CACHE:
        return _PRODUCT_TYPE_CACHE
    
    # Load synchronously - this is acceptable for one-time initialization
    # The cache ensures this only happens once per process lifetime
    _PRODUCT_TYPE_LOAD_ATTEMPTED = True
    _PRODUCT_TYPE_CACHE = _load_product_type_translations_sync(lang)
    return _PRODUCT_TYPE_CACHE


class HeimanHttpClient:
    """Low-level HTTP client for Heiman API.
    
    This class handles the raw HTTP requests with proper authentication headers.
    """

    def __init__(
            self,
            api_url: str,
            access_token: str,
            timeout: int = 30,
    ) -> None:
        """Initialize HTTP client.
        
        Args:
            api_url: Base API URL
            access_token: Access token for authentication
            timeout: Request timeout in seconds (default: 30)
        """
        self.api_url = api_url.rstrip("/")
        self.access_token = access_token
        self._timeout = timeout
        self._session: Optional[aiohttp.ClientSession] = None

    async def _get_session(self) -> aiohttp.ClientSession:
        """Get or create aiohttp session."""
        if self._session is None or self._session.closed:
            timeout = aiohttp.ClientTimeout(total=self._timeout)
            self._session = aiohttp.ClientSession(timeout=timeout)
        return self._session

    async def close(self) -> None:
        """Close the HTTP session."""
        if self._session and not self._session.closed:
            await self._session.close()

    def _get_headers(self) -> dict[str, str]:
        """Get request headers with authentication."""
        headers = {
            # 使用小写 header 名称（与官方 App 一致）
            "content-type": "application/json",
            "authorization": f"bearer {self.access_token}",
            "tenant-id": "1"
        }

        return headers

    async def request(
            self,
            method: str,
            endpoint: str,
            data: Optional[dict[str, Any]] = None,
            params: Optional[dict[str, Any]] = None,
            max_retries: int = 5,  # 增加到 5 次
            retry_delay: float = 3.0,  # 增加到 3 秒
    ) -> dict[str, Any]:
        """Make HTTP request to Heiman API with automatic retry.
        
        Args:
            method: HTTP method (GET, POST, PUT, DELETE)
            endpoint: API endpoint path
            data: Request body data
            params: Query parameters
            max_retries: Maximum number of retries for server busy errors (default: 3)
            retry_delay: Delay between retries in seconds (default: 2.0)
            
        Returns:
            JSON response as dictionary
            
        Raises:
            HeimanConnectionError: If network request fails
            HeimanApiError: If API returns error
        """
        url = f"{self.api_url}{endpoint}"
        headers = self._get_headers()

        try:
            session = await self._get_session()

            for attempt in range(max_retries):
                async with session.request(
                        method,
                        url,
                        json=data if method in ["POST", "PUT"] else None,
                        params=params if method == "GET" else None,
                        headers=headers,
                ) as response:
                    result = await response.json()
                    _LOGGER.debug(f"{method} {url} -> {response.status} {result}")

                    # Check for API-level errors (status code 200 but business logic error)
                    if response.status == 200:
                        # Heiman API uses 'status' field for business logic status
                        status = result.get("status")
                        message = result.get("message", "")

                        # Check if it's a server busy error that we can retry
                        is_server_busy = (
                                status == 1012000014 or
                                "busy" in message.lower() or
                                "server is busy" in message.lower() or
                                (status and status >= 1012000000 and status < 1012000100)
                        )

                        if is_server_busy:
                            if attempt < max_retries - 1:
                                _LOGGER.warning(
                                    f"Server busy ({status}): {message}. "
                                    f"Retry {attempt + 1}/{max_retries} in {retry_delay}s..."
                                )
                                import asyncio
                                await asyncio.sleep(retry_delay)
                                continue
                            else:
                                raise HeimanApiError(
                                    message=f"Server still busy after {max_retries} attempts: {message}",
                                    error_code=status,
                                    raw_response=result,
                                )

                        # Check for other API errors
                        # Success status codes: 200, 1000000000
                        is_success = (status == 200 or status == 1000000000 or
                                      (status and status < 300) or status is None)

                        if not is_success:
                            error_msg = message or result.get("msg", "Unknown API error")
                            raise HeimanApiError(
                                message=error_msg,
                                error_code=status,
                                raw_response=result,
                            )

                    # HTTP error status codes
                    if response.status >= 400:
                        error_msg = result.get("message", "Unknown API error")
                        error_code = result.get("code")

                        if response.status == 401:
                            raise HeimanAuthError(
                                message="Authentication failed - token may be expired",
                                error_code=error_code,
                                raw_response=result,
                            )

                        raise HeimanApiError(
                            message=error_msg,
                            error_code=error_code,
                            raw_response=result,
                        )

                    # Success
                    return result

            # Should not reach here
            raise HeimanApiError(
                message=f"Request failed after {max_retries} attempts",
                raw_response={},
            )

        except aiohttp.ClientError as err:
            raise HeimanConnectionError(
                message=f"Network error: {str(err)}",
            ) from err
        except Exception as err:
            raise HeimanApiError(
                message=f"Unexpected error: {str(err)}",
            ) from err

    async def get(
            self,
            endpoint: str,
            params: Optional[dict[str, Any]] = None,
    ) -> dict[str, Any]:
        """Make GET request."""
        return await self.request("GET", endpoint, params=params)

    async def post(
            self,
            endpoint: str,
            data: Optional[dict[str, Any]] = None,
    ) -> dict[str, Any]:
        """Make POST request."""
        return await self.request("POST", endpoint, data=data)

    async def put(
            self,
            endpoint: str,
            data: Optional[dict[str, Any]] = None,
    ) -> dict[str, Any]:
        """Make PUT request."""
        return await self.request("PUT", endpoint, data=data)

    async def delete(
            self,
            endpoint: str,
    ) -> dict[str, Any]:
        """Make DELETE request."""
        return await self.request("DELETE", endpoint)

    def update_access_token(self, access_token: str) -> None:
        """Update access token.
        
        Args:
            access_token: New access token
        """
        self.access_token = access_token
        _LOGGER.debug("Access token updated")


class HeimanCloudClient:
    """High-level Heiman cloud API client.
    
    This class provides convenient methods for common API operations
    like getting users, homes, and devices.
    """

    def __init__(
            self,
            http_client: HeimanHttpClient,
    ) -> None:
        """Initialize cloud client.
        
        Args:
            http_client: Low-level HTTP client instance
        """
        self.http_client = http_client
        self._home_id: Optional[str] = None
        self._user_id: Optional[str] = None

    @property
    def home_id(self) -> Optional[str]:
        """Get current home ID."""
        return self._home_id

    @home_id.setter
    def home_id(self, value: str) -> None:
        """Set current home ID."""
        self._home_id = value

    @property
    def user_id(self) -> Optional[str]:
        """Get current user ID."""
        return self._user_id

    async def _ensure_authenticated(self) -> None:
        """Ensure we have a valid access token."""
        # Token is managed externally, just verify it exists
        if not self.http_client.access_token:
            raise HeimanAuthError(message="Not authenticated")

    async def async_get_user_info(self) -> HeimanUser:
        """Get current user information.
        
        Returns:
            HeimanUser object with user details
            
        Raises:
            HeimanApiError: If API request fails
        """
        await self._ensure_authenticated()

        endpoint = "/api-app/appUser/get/info"
        result = await self.http_client.get(endpoint)
        _LOGGER.debug(f"Get user info response: {result}")

        # Handle both 'data' and 'result' field names
        user_data = result.get("data", {}) or result.get("result", {})

        if not user_data:
            raise HeimanApiError(
                message="No user data returned from API",
                raw_response=result,
            )

        user = HeimanUser(
            user_id=user_data.get("id", "") or user_data.get("userId", ""),
            email=user_data.get("email", ""),
            nickname=user_data.get("nickname"),
            phone=user_data.get("phone"),
            avatar=user_data.get("avatar"),
            raw_data=user_data,
        )

        if not user.user_id:
            _LOGGER.error(f"User ID is empty in response: {user_data}")
            raise HeimanApiError(
                message="User ID is empty in API response",
                raw_response=result,
            )

        self._user_id = user.user_id
        _LOGGER.debug(f"Retrieved user ID: {user.user_id}")
        return user

    async def async_get_homes(self) -> list[HeimanHome]:
        """Get list of homes for current user.
        
        Returns:
            List of HeimanHome objects
            
        Raises:
            HeimanApiError: If API request fails
        """
        await self._ensure_authenticated()

        # Ensure we have a user ID
        if not self.user_id:
            _LOGGER.warning("User ID is empty, trying to get user info first")
            await self.async_get_user_info()

        endpoint = "/api-app/homeUserRelation/get/homeList"
        data = {"userId": self.user_id}

        _LOGGER.debug(f"Getting homes - Endpoint: {endpoint}, User ID: {self.user_id}")
        result = await self.http_client.post(endpoint, data=data)
        _LOGGER.debug(f"Get homes response: {result}")

        # Handle both 'data' and 'result' field names
        homes_data = result.get("data", []) or result.get("result", [])

        homes = []
        for home_data in homes_data:
            home = HeimanHome(
                home_id=home_data.get("homeId", ""),
                home_name=home_data.get("homeName", ""),
                user_id=home_data.get("userId", ""),
                room_count=home_data.get("roomCount", 0),
                device_count=home_data.get("deviceCount", 0),
                cover_url=home_data.get("coverUrl"),
                raw_data=home_data,
            )
            homes.append(home)

        _LOGGER.debug(f"Retrieved {len(homes)} homes")
        return homes

    async def async_get_devices(
            self,
            home_id: Optional[str] = None,
            page_number: int = 1,
            page_size: int = 100,
    ) -> dict[str, HeimanDevice]:
        """Get list of devices in specified home.
        
        Args:
            home_id: Home ID (uses current home_id if not specified)
            page_number: Page number for pagination
            page_size: Number of devices per page
            
        Returns:
            Dictionary mapping device_id to HeimanDevice objects
            
        Raises:
            HeimanApiError: If API request fails
        """
        await self._ensure_authenticated()

        target_home_id = home_id or self._home_id
        if not target_home_id:
            raise HeimanApiError(message="No home ID specified")

        _LOGGER.debug("=" * 80)
        _LOGGER.debug("Fetching devices from cloud API")
        _LOGGER.debug("=" * 80)
        _LOGGER.debug(">>> Home ID: %s", target_home_id)
        _LOGGER.debug(">>> User ID: %s", self.user_id)
        _LOGGER.debug(">>> Page: %s/%s", page_number, page_size)

        endpoint = "/api-app/device/get/listByPage"

        # Build request data according to protocol
        request_data = {
            "help": {
                "pageSize": page_size,
                "pageNumber": page_number,
            },
            "custom": {
                "homeId": target_home_id,
                "secureId": "",  # Can be set if available
                "userId": self.user_id,
                # Request all property identifiers
                "propertyIdentifiers": [],
            },
        }

        _LOGGER.debug(">>> Request payload: %s", request_data)

        result = await self.http_client.post(endpoint, data=request_data)
        _LOGGER.debug(">>> Devices API response type: %s", type(result))
        _LOGGER.debug(
            ">>> Devices API response (first 1000 chars): %s",
            str(result)[:1000],
        )

        # Handle both 'data' and 'result' field names
        # API returns: {status, result: {pageIndex, pageSize, total, data: [...]}, message}
        # OR: {status, data: {pageIndex, pageSize, total, list: [...]}, message}
        result_data = result.get("data", {}) or result.get("result", {})

        if isinstance(result_data, dict):
            devices_data = result_data.get("list", []) or result_data.get("data", [])
            total = result_data.get("total", 0)
            page_index = result_data.get("pageIndex", page_number)
            page_size_actual = result_data.get("pageSize", page_size)
        else:
            _LOGGER.warning("Unexpected result_data format: %s", result_data)
            devices_data = []
            total = 0
            page_index = page_number
            page_size_actual = page_size

        devices = {}
        for device_data in devices_data:
            device = self._parse_device_data(device_data)
            devices[device.device_id] = device

        _LOGGER.info(
            "Retrieved %s/%s devices from home %s (page %s/%s)",
            len(devices),
            total,
            target_home_id,
            page_index,
            (total + page_size_actual - 1) // page_size_actual if page_size_actual > 0 else 1,
        )

        # Log details of first few devices
        for idx, device in enumerate(list(devices.values())[:5]):
            _LOGGER.debug(
                "Device %d: id=%s, name=%s, model=%s, online=%s, properties=%d",
                idx,
                device.device_id,
                device.device_name,
                device.model,
                device.online,
                len(device.properties),
            )
        if len(devices) > 5:
            _LOGGER.debug("... and %s more devices", len(devices) - 5)

        # Check if API total matches actual data count
        if len(devices) != total:
            _LOGGER.warning(
                "WARNING: API reports %s total devices but returned only %s devices in data array",
                total,
                len(devices),
            )
            _LOGGER.warning(
                "This might be a pagination issue or some devices are filtered out",
            )

        _LOGGER.debug("=" * 80)
        return devices

    def _parse_device_data(self, device_data: dict[str, Any]) -> HeimanDevice:
        """Parse raw device data into HeimanDevice object.
        
        Args:
            device_data: Raw device data from API
            
        Returns:
            HeimanDevice object
        """
        # API returns flat structure, not nested in "deviceInfo"
        # Extract basic device info directly from root level
        device_id = device_data.get("id", "") or device_data.get("deviceId", "")
        device_name = device_data.get("deviceName", "")
        one_name = device_data.get("name", "")
        product_id = device_data.get("productId", "")
        home_id = device_data.get("homeId", "")
        room_id = device_data.get("roomId")

        # Handle deviceType which can be dict or string
        device_type_raw = device_data.get("deviceType")
        if isinstance(device_type_raw, dict):
            device_type = device_type_raw.get("value", "")
        else:
            device_type = device_type_raw or ""

        # Get model from productName or model field
        # Extract model number from productName (e.g., "烟雾报警器-HM2SA-1W(868MHz)" -> "HM2SA-1W")
        model = device_data.get("model", "")
        if not model:
            product_name = device_data.get("productName", "")
            if product_name:
                # Match pattern: letters, numbers, and hyphens before Chinese or English brackets
                # Handles both "(868MHz)" and "（868MHz）"
                match = re.search(r'([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\s*[()（]', product_name)
                if match:
                    model = match.group(1)
                else:
                    # Fallback to full product name if no pattern found
                    model = product_name
        
        # Use translated product name if available
        # product_type_map = _get_product_type_translations()
        # if product_id and product_id in product_type_map:
        #     model = product_type_map[product_id]
        #     _LOGGER.debug(f"Using translated product name for {product_id}: {model}")

        # Parse online status from state
        state_raw = device_data.get("state", {})
        if isinstance(state_raw, dict):
            online = state_raw.get("value", "offline") == "online"
        else:
            online = device_data.get("online", False)

        # Parse firmware version - prioritize firmwareInfo.version from detail endpoint
        firmware_version = None
        firmware_info = device_data.get("firmwareInfo")
        if firmware_info and isinstance(firmware_info, dict):
            # Try to get version from firmwareInfo.version first
            firmware_version = firmware_info.get("version")
            # Fallback to firmwareInfo.properties if version not available
            if not firmware_version:
                properties = firmware_info.get("properties", {})
                if isinstance(properties, dict):
                    # Try to get version from properties (first available)
                    for prop_value in properties.values():
                        if prop_value:
                            firmware_version = str(prop_value)
                            break
        # Fallback to old firmwareVersion field
        if not firmware_version:
            firmware_version = device_data.get("firmwareVersion")

        # Parse properties
        # properties_data = device_data.get("properties", [])
        properties = {}

        # Get product_id for special handling
        product_id = device_data.get("productId", "")

        # Special handling for gateway devices (网关设备)
        if product_id in [
            "2034958781083516928",
            "2018250377056022528",
            "2001581958272577536",
            "1976552577824727040",
            "1960251398905970688",
            "1960250096146759680",
            "1932322027567980544",
            "1901601085789986816",
            "1870278823705071616",
            "1810843560026951680",
            "1733421468953686016",
            "1712723441528012800",
            "1712402758738575360",
            "1712401376535052288",
            "1712400967301005312",
            "1712360385354596352",
            "1712007899645149184",
        ]:
            if product_id in ["1960250096146759680"]:
                # Add AlarmSoundOption (select)
                properties["AlarmSoundOption"] = DeviceProperty(
                    identifier="AlarmSoundOption",
                    name="Alarm Tempo",
                    value=None,
                    unit=None,
                    data_type="enum",
                    entity="select",
                    readable=True,
                    writable=True,
                    description="Sound Option Selection",
                )
            # Add LightSwitch (switch)
            properties["LightSwitch"] = DeviceProperty(
                identifier="LightSwitch",
                name="Indicator",
                value=None,
                unit=None,
                data_type="bool",
                entity="switch",
                readable=True,
                writable=True,
                description="Indicator Light Control",
            )
            # Add TimeZone
            properties["TimeZone"] = DeviceProperty(
                identifier="TimeZone",
                name="Time Zone",
                value=None,
                unit=None,
                data_type="int",
                entity="sensor",
                readable=True,
                writable=True,
                description="Device Time Zone Setting",
            )
            # Add MAC address sensor
            properties["DeviceINFO_MAC"] = DeviceProperty(
                identifier="DeviceINFO_MAC",
                name="MAC Address",
                value=one_name,
                unit=None,
                data_type="string",
                entity="sensor",
                readable=True,
                writable=False,
                description="Device MAC Address",
            )
            # Add signal strength level sensor
            properties["DeviceINFO_DBM_Level"] = DeviceProperty(
                identifier="DeviceINFO_DBM_Level",
                name="Signal Strength Level",
                value=None,
                unit=None,
                data_type="enum",
                entity="sensor",
                readable=True,
                writable=False,
                description="Signal Strength Level (Strong/Medium/Weak/Very Weak)",
            )
            # Add IP address sensor
            properties["DeviceINFO_IP"] = DeviceProperty(
                identifier="DeviceINFO_IP",
                name="IP Address",
                value=None,
                unit=None,
                data_type="string",
                entity="sensor",
                readable=True,
                writable=False,
                description="Device IP Address",
            )
            
            # Note: DeviceINFO object will be parsed separately to extract MAC, DBM, DBM_Level values

        # Special handling for smoke sensor products (烟雾传感器)
        if product_id in [
            "2029440661815095296",
            "2029438274199154688",
            "2013145744913657856",
            "2007989417262379008",
            "1991745959373635584",
            "1986705377032818688",
            "1985528410954682368",
            "1985526736966012928",
            "1981621464757325824",
            "1968114912378396672",
            "1905532161226346496",
            "1901600411274600448",
            "1825452011297071104",
            "1810857540850143232",
            "1734821218500292608",
        ]:
            # Add MAC address sensor
            properties["DeviceMac"] = DeviceProperty(
                identifier="DeviceMac",
                name="MAC Address",
                value=one_name,
                unit=None,
                data_type="string",
                entity="sensor",
                readable=True,
                writable=False,
                description="Device MAC Address",
            )
            # Add RemoteLocate (button)
            properties["RemoteLocate"] = DeviceProperty(
                identifier="RemoteLocate",
                name="Locate Alarm",
                value=None,
                unit=None,
                data_type="bool",
                entity="button",
                readable=False,
                writable=True,
                description="Remote Locate Function",
            )
            # Add RemoteCheck (button)
            properties["RemoteCheck"] = DeviceProperty(
                identifier="RemoteCheck",
                name="Test Alarm",
                value=None,
                unit=None,
                data_type="bool",
                entity="button",
                readable=False,
                writable=True,
                description="Test Alarm Function",
            )
            # Add Mute (button)
            properties["Mute"] = DeviceProperty(
                identifier="Mute",
                name="Hush Alarm",
                entity="button",
                value=None,
                unit=None,
                data_type="bool",
                readable=False,
                writable=True,
                description="Hush Alarm Function",
            )
            # Add LightSwitch (switch)
            properties["LightSwitch"] = DeviceProperty(
                identifier="LightSwitch",
                name="Indicator",
                entity="switch",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=True,
                description="Indicator Light Control",
            )
            # Add SmokeSensorState (binary_sensor)
            properties["SmokeSensorState"] = DeviceProperty(
                identifier="SmokeSensorState",
                name="Smoke Alarm",
                entity="binary_sensor",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=False,
                description="Smoke Detection Status",
            )
            # Add CurrentTemperature (sensor)
            properties["CurrentTemperature"] = DeviceProperty(
                identifier="CurrentTemperature",
                name="Device Temperature",
                entity="sensor",
                value=None,
                unit="°C",
                data_type="double",
                readable=True,
                writable=False,
                description="Current Environment Temperature",
            )
            # Add TamperState (binary_sensor)
            properties["TamperState"] = DeviceProperty(
                identifier="TamperState",
                name="Tamper Alarm",
                entity="binary_sensor",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=False,
                description="Device Tamper Detection Status",
            )
            # Add UnderVoltError (binary_sensor)
            properties["UnderVoltError"] = DeviceProperty(
                identifier="UnderVoltError",
                name="Low Battery Alarm",
                entity="binary_sensor",
                value=None,
                unit=None,
                data_type="int",
                readable=True,
                writable=False,
                description="Low Battery Voltage Alert",
            )
            # Add BatteryPercentage (sensor)
            properties["BatteryPercentage"] = DeviceProperty(
                identifier="BatteryPercentage",
                name="Battery Level",
                entity="sensor",
                value=None,
                unit="%",
                data_type="int",
                readable=True,
                writable=False,
                description="Battery Level Percentage",
            )

        # Special handling for water leak sensor products (水浸传感器)
        if product_id in [
            "2003374935470960640",
            "1925004014149328896",
            "1925003834175938560",
            "1712640220090007552",
            "1712366595122331648",
            "1902647452417347584",
            "1902647647511203840",
            "1712024520782708736",
        ]:
            # Add MAC address sensor
            properties["DeviceMac"] = DeviceProperty(
                identifier="DeviceMac",
                name="MAC Address",
                entity="sensor",
                value=one_name,
                unit=None,
                data_type="string",
                readable=True,
                writable=False,
                description="Device MAC Address",
            )
            # Add FreezingPointEnable (switch)
            properties["FreezingPointEnable"] = DeviceProperty(
                identifier="FreezingPointEnable",
                name="Freeze Detection",
                entity="switch",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=True,
                description="Enable/Disable Freezing Point Alarm",
            )
            # Add BuzzerEnable (switch)
            properties["BuzzerEnable"] = DeviceProperty(
                identifier="BuzzerEnable",
                name="Alarm Sound",
                entity="switch",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=True,
                description="Enable/Disable Buzzer Sound",
            )
            # Add Mute (button)
            properties["Mute"] = DeviceProperty(
                identifier="Mute",
                name="Hush Alarm",
                entity="button",
                value=None,
                unit=None,
                data_type="bool",
                readable=False,
                writable=True,
                description="Hush Alarm Function",
            )
            # Add LightSwitch (switch)
            properties["LightSwitch"] = DeviceProperty(
                identifier="LightSwitch",
                name="Indicator",
                entity="switch",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=True,
                description="Indicator Light Control",
            )
            # Add RemoteCheck (button)
            properties["RemoteCheck"] = DeviceProperty(
                identifier="RemoteCheck",
                name="Test Alarm",
                entity="button",
                value=None,
                unit=None,
                data_type="bool",
                readable=False,
                writable=True,
                description="Test Alarm Function",
            )
            # Add WaterSensorState (binary_sensor)
            properties["WaterSensorState"] = DeviceProperty(
                identifier="WaterSensorState",
                name="Water Leakage Alarm",
                entity="binary_sensor",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=False,
                description="Water Leak Detection Status",
            )
            # Add FreezingPointAlarm (binary_sensor)
            properties["FreezingPointAlarm"] = DeviceProperty(
                identifier="FreezingPointAlarm",
                name="Freeze Alarm",
                entity="binary_sensor",
                value=None,
                unit=None,
                data_type="bool",
                readable=True,
                writable=False,
                description="Freezing Point Detection Status",
            )
            # Add UnderVoltError (binary_sensor)
            properties["UnderVoltError"] = DeviceProperty(
                identifier="UnderVoltError",
                name="Low Battery Alarm",
                entity="binary_sensor",
                value=None,
                unit=None,
                data_type="int",
                readable=True,
                writable=False,
                description="Low Battery Voltage Alert",
            )
            # Add BatteryPercentage (sensor)
            properties["BatteryPercentage"] = DeviceProperty(
                identifier="BatteryPercentage",
                name="Battery Level",
                entity="sensor",
                value=None,
                unit="%",
                data_type="int",
                readable=True,
                writable=False,
                description="Battery Level Percentage",
            )

        # Create device object
        device = HeimanDevice(
            device_id=device_id,
            device_name=device_name,
            product_id=product_id,
            home_id=home_id,
            room_id=room_id,
            device_type=device_type,
            model=model,
            firmware_version=firmware_version,
            hardware_version=device_data.get("hardwareVersion"),
            serial_number=device_data.get("serialNumber"),
            mac_address=device_data.get("macAddress"),
            ip_address=device_data.get("ipAddress"),
            online=online,
            properties=properties,
            raw_data=device_data,
        )
        return device

    async def async_control_device(
            self,
            device_id: str,
            property_identifier: str,
            value: Any,
    ) -> bool:
        """Control device by setting property value.

        Args:
            device_id: Target device ID
            property_identifier: Property to control
            value: Value to set

        Returns:
            True if control successful

        Raises:
            HeimanApiError: If control request fails
        """
        await self._ensure_authenticated()

        endpoint = "/api-app/device/control"

        request_data = {
            "deviceId": device_id,
            "commands": [
                {
                    "identifier": property_identifier,
                    "value": value,
                }
            ],
        }

        result = await self.http_client.post(endpoint, data=request_data)

        success = result.get("success", False)
        if not success:
            raise HeimanApiError(
                message=result.get("message", "Device control failed"),
                raw_response=result,
            )

        _LOGGER.debug(f"Successfully controlled device {device_id}")
        return True

    async def _async_get_device_detail(self, device_id: str) -> dict | None:
        """Get device detail via /api-saas/device/instance/app/11/{device_id}/detail.

        Args:
            device_id: The device ID

        Returns:
            Device detail dict containing deriveMetadata field, or None on error
        """
        if not device_id:
            _LOGGER.error("Device ID is empty for getting device detail")
            return None

        try:
            endpoint = f"/api-saas/device/instance/app/11/{device_id}/detail"
            response = await self.http_client.get(endpoint)
            
            # Response structure: {message, result: {...}, status, timestamp}
            # We need to extract the 'result' field which contains deriveMetadata
            if isinstance(response, dict):
                # Extract the actual device detail from 'result' field
                device_detail = response.get("result", {})
                
                if isinstance(device_detail, dict):
                    _LOGGER.debug(
                        "Got device detail for %s: keys=%s",
                        device_id,
                        list(device_detail.keys()),
                    )
                    return device_detail
                else:
                    _LOGGER.warning(
                        "Unexpected result format for %s: result is not a dict",
                        device_id,
                    )
                    return None
                    
            _LOGGER.warning(
                "Unexpected device detail response type for %s: %s",
                device_id,
                type(response),
            )
            return None
        except Exception as err:
            _LOGGER.exception(
                "Failed to get device detail for %s: %s",
                device_id,
                err,
            )
            return None

    async def async_get_device_properties(
            self,
            device_id: str,
    ) -> dict[str, Any]:
        """Get current properties of a device.

        Args:
            device_id: Device ID

        Returns:
            Dictionary of property identifier to value

        Raises:
            HeimanApiError: If request fails
        """
        await self._ensure_authenticated()

        endpoint = "/api-app/device/get/properties"

        request_data = {
            "deviceId": device_id,
            "propertyIdentifiers": [],  # Empty means all properties
        }

        result = await self.http_client.post(endpoint, data=request_data)

        properties_data = result.get("data", [])
        properties = {}

        for prop_data in properties_data:
            identifier = prop_data.get("identifier", "")
            value = prop_data.get("value")
            properties[identifier] = value

        return properties

    async def close(self) -> None:
        """Close the client."""
        await self.http_client.close()


# Import here to avoid circular imports
from .models import DeviceProperty
