import logging
import traceback
from typing import Dict, List, Any, Optional

logger = logging.getLogger(__name__)

class FunctionalZoneIdentifier:
    """
    作為功能區域辨識的主要窗口
    整合區域評估和場景特定的區域辨識邏輯,提供統一的功能區域辨識接口
    """

    def __init__(self, zone_evaluator=None, scene_zone_identifier=None, scene_viewpoint_analyzer=None, object_categories=None):
        """
        初始化功能區域識別器

        Args:
            zone_evaluator: 區域評估器實例
            scene_zone_identifier: 場景區域辨識器實例
            scene_viewpoint_analyzer: 場景視角分析器
        """
        try:
            self.zone_evaluator = zone_evaluator
            self.scene_zone_identifier = scene_zone_identifier

            self.scene_viewpoint_analyzer = scene_viewpoint_analyzer
            self.viewpoint_detector = scene_viewpoint_analyzer
            self.OBJECT_CATEGORIES = object_categories or {}

            logger.info("FunctionalZoneIdentifier initialized successfully with SceneViewpointAnalyzer")

        except Exception as e:
            logger.error(f"Failed to initialize FunctionalZoneIdentifier: {str(e)}")
            logger.error(traceback.format_exc())
            raise

    def identify_functional_zones(self, detected_objects: List[Dict], scene_type: str) -> Dict:
        """
        識別場景內的功能區域,具有針對不同視角和文化背景的改進檢測能力。
        如果偵測到 is_landmark=True 的物件,則優先直接呼叫 identify_landmark_zones 並回傳結果。
        """

        try:
            # 1. 如果沒有啟用地標功能,就先把所有有 is_landmark=True 的物件過濾掉
            if not getattr(self, 'enable_landmark', True):
                detected_objects = [obj for obj in detected_objects if not obj.get("is_landmark", False)]

            # 2. 只要檢測到任何 is_landmark=True 的物件,立即優先使用 identify_landmark_zones
            landmark_objects = [obj for obj in detected_objects if obj.get("is_landmark", False)]
            if landmark_objects and self.scene_zone_identifier:
                lm_zones = self.scene_zone_identifier.identify_landmark_zones(landmark_objects)
                return self._standardize_zone_keys_and_descriptions(lm_zones)

            # 3. city_street
            if scene_type in ["tourist_landmark", "natural_landmark", "historical_monument"]:
                scene_type = "city_street"

            # 4.  判斷與物件數量檢查
            if self.zone_evaluator:
                should_identify = self.zone_evaluator.evaluate_zone_identification_feasibility(
                    detected_objects, scene_type
                )
                if not should_identify:
                    logger.info(f"Zone identification not feasible for scene type '{scene_type}'")
                    return {}
            else:
                if len(detected_objects) < 2:
                    logger.info("Insufficient objects for zone identification")
                    return {}

            # 5. 建立 category_regions
            category_regions = self._build_category_regions_mapping(detected_objects)
            zones = {}

            # 6. 檢測場景視角
            viewpoint_info = {"viewpoint": "eye_level"}
            if self.scene_viewpoint_analyzer:
                viewpoint_info = self.scene_viewpoint_analyzer.detect_scene_viewpoint(detected_objects)

            # 7. 根據不同 scene_type 使用各種自己的區域辨識
            if scene_type in ["living_room", "bedroom", "dining_area", "kitchen", "office_workspace", "meeting_room"]:
                if self.scene_zone_identifier:
                    raw_zones = self.scene_zone_identifier.identify_indoor_zones(
                        category_regions, detected_objects, scene_type
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(raw_zones))

            elif scene_type in ["city_street", "parking_lot", "park_area"]:
                if self.scene_zone_identifier:
                    raw_zones = self.scene_zone_identifier.identify_outdoor_general_zones(
                        category_regions, detected_objects, scene_type
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(raw_zones))

            elif "aerial" in scene_type or viewpoint_info.get("viewpoint") == "aerial":
                if self.scene_zone_identifier:
                    raw_zones = self.scene_zone_identifier.identify_aerial_view_zones(
                        category_regions, detected_objects, scene_type
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(raw_zones))

            elif "asian" in scene_type:
                if self.scene_zone_identifier:
                    asian_zones = self.scene_zone_identifier.identify_asian_cultural_zones(
                        category_regions, detected_objects, scene_type
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(asian_zones))

            elif scene_type == "urban_intersection":
                if self.scene_zone_identifier:
                    raw_zones = self.scene_zone_identifier.identify_intersection_zones(
                        category_regions, detected_objects, viewpoint_info.get("viewpoint")
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(raw_zones))
                    used_tl_count_per_region = {}
                    for zone_info in raw_zones.values():
                        obj_list = zone_info.get("objects", [])
                        if "traffic light" in obj_list:
                            rg = zone_info.get("region", "")
                            count_in_zone = obj_list.count("traffic light")
                            used_tl_count_per_region[rg] = used_tl_count_per_region.get(rg, 0) + count_in_zone

                    signal_regions = {}
                    for t in [obj for obj in detected_objects if obj.get("class_id") == 9]:
                        region = t.get("region", "")
                        signal_regions.setdefault(region, []).append(t)

                    for idx, (region, signals) in enumerate(signal_regions.items()):
                        total_in_region = len(signals)
                        used_in_region = used_tl_count_per_region.get(region, 0)
                        remaining_in_region = total_in_region - used_in_region

                        if remaining_in_region > 0:
                            direction = self._get_directional_description(region)
                            if direction and direction != "central":
                                zone_key = f"{direction} traffic control area"
                            else:
                                zone_key = "primary traffic control area" if idx == 0 else "auxiliary traffic control area"

                            if zone_key in zones:
                                suffix = 1
                                new_key = f"{zone_key} ({suffix})"
                                while new_key in zones:
                                    suffix += 1
                                    new_key = f"{zone_key} ({suffix})"
                                zone_key = new_key

                            zones[zone_key] = {
                                "region": region,
                                "objects": ["traffic light"] * remaining_in_region,
                                "description": f"Traffic control area with {remaining_in_region} traffic lights in {region}"
                            }

                    for region, signals in signal_regions.items():
                        used = used_tl_count_per_region.get(region, 0)
                        total = len(signals)
                        remaining = total - used
                        # print(f"[DEBUG] Region '{region}': Total TL = {total}, Used in crossing = {used}, Remaining = {remaining}")

            elif scene_type == "financial_district":
                if self.scene_zone_identifier:
                    fd_zones = self.scene_zone_identifier.identify_financial_district_zones(
                        category_regions, detected_objects
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(fd_zones))

            elif scene_type == "upscale_dining":
                if self.scene_zone_identifier:
                    ud_zones = self.scene_zone_identifier.identify_upscale_dining_zones(
                        category_regions, detected_objects
                    )
                    zones.update(self._standardize_zone_keys_and_descriptions(ud_zones))

            else:
                # 如果不是上述任何一種場景,就用「預設功能區」
                default_zones = self._identify_default_zones(category_regions, detected_objects)
                zones.update(self._standardize_zone_keys_and_descriptions(default_zones))

            # 8. 如果此時 zones 仍為空,就會變成 default → basic → fallback
            if not zones:
                default_zones = self._identify_default_zones(category_regions, detected_objects)
                if default_zones:
                    zones.update(self._standardize_zone_keys_and_descriptions(default_zones))
                else:
                    basic_zones = self._create_basic_zones_from_objects(detected_objects, scene_type)
                    zones.update(self._standardize_zone_keys_and_descriptions(basic_zones))

            # 通用 fallback:把所有還沒被列出的 (class_name, region) 通通補進去
            fallback_zones = self._generate_category_fallback_zones(detected_objects, zones)
            zones.update(fallback_zones)

            # Debug: 列印出各功能區的 traffic light 統計
            total_tl_in_zones = 0
            for zone_key, zone_info in zones.items():
                if isinstance(zone_info, dict):
                    sub_objs = zone_info.get("objects", [])
                else:
                    sub_objs = []
                t_in_zone = [obj for obj in sub_objs if obj == "traffic light"]
                # print(f"[DEBUG] identify_functional_zones - Zone '{zone_key}' has {len(t_in_zone)} traffic light(s).")
                total_tl_in_zones += len(t_in_zone)
            # print(f"[DEBUG] identify_functional_zones - Total traffic lights in zones: {total_tl_in_zones}")

            logger.info(f"Identified {len(zones)} functional zones for scene type '{scene_type}'")
            return zones

        except Exception as e:
            logger.error(f"Error identifying functional zones: {str(e)}")
            logger.error(traceback.format_exc())
            return {}

    def _standardize_zone_keys_and_descriptions(self, raw_zones: Dict) -> Dict:
        """
        標準化區域鍵名和描述,將內部標識符轉換為描述性名稱

        Args:
            raw_zones: 原始區域識別結果

        Returns:
            Dict: 標準化後的區域字典
        """
        try:
            standardized_zones = {}

            for zone_key, zone_data in raw_zones.items():
                # 生成描述性的區域鍵名
                descriptive_key = self._generate_descriptive_zone_key(zone_key, zone_data)

                # 確保區域描述也經過標準化
                if isinstance(zone_data, dict) and "description" in zone_data:
                    zone_data["description"] = self._enhance_zone_description(zone_data["description"], zone_data)

                standardized_zones[descriptive_key] = zone_data

            return standardized_zones

        except Exception as e:
            logger.error(f"Error standardizing zone keys and descriptions: {str(e)}")
            return raw_zones

    def _generate_descriptive_zone_key(self, original_key: str, zone_data: Dict) -> str:
        """
        基於區域內容生成描述性的鍵名
        核心修改:只要該區域內有任一個 'traffic light',就優先回傳 'traffic control zone',
        """
        try:
            objects = zone_data.get("objects", [])
            region = zone_data.get("region", "")

            # 優先檢查是否含有 traffic light
            if any(obj == "traffic light" or "traffic light" in obj for obj in objects):
                return "traffic control zone"

            # 如果沒有 traffic light,才繼續分析「主要物件」順序
            primary_objects = self._analyze_primary_objects(objects)

            # 依序檢查人、車、家具、紅綠燈等
            if "person" in primary_objects:
                if len([o for o in objects if o == "person"]) > 1:
                    return "pedestrian activity area"
                else:
                    return "individual activity zone"
            elif any(vehicle in primary_objects for vehicle in ["car", "truck", "bus", "motorcycle"]):
                return "vehicle movement area"
            elif any(furniture in primary_objects for furniture in ["chair", "table", "sofa", "bed"]):
                return "furniture arrangement area"

            # 若上述都不符合,改用「基於位置」做 fallback
            position_descriptions = {
                "top_left": "upper left area",
                "top_center": "upper central area",
                "top_right": "upper right area",
                "middle_left": "left side area",
                "middle_center": "main crossing area",
                "middle_right": "right side area",
                "bottom_left": "lower left area",
                "bottom_center": "lower central area",
                "bottom_right": "lower right area"
            }
            if region in position_descriptions:
                return position_descriptions[region]

            # 再次檢查主要物件,給出另一種 fallback 命名
            if primary_objects:
                if "traffic light" in primary_objects:
                    return "traffic control zone"
                elif any(vehicle in primary_objects for vehicle in ["car", "truck", "bus"]):
                    return "vehicle movement area"
                elif "person" in primary_objects:
                    return "pedestrian activity area"

            # 最後最後的備用名稱
            return "activity area"

        except Exception as e:
            logger.warning(f"Error generating descriptive key for '{original_key}': {str(e)}")
            return "activity area"

    def _analyze_primary_objects(self, objects: List[str]) -> List[str]:
        """
        分析區域中的主要物件類型

        Args:
            objects: 物件名稱列表

        Returns:
            List[str]: 主要物件類型列表
        """
        try:
            # 計算物件出現頻率
            object_counts = {}
            for obj in objects:
                normalized_obj = obj.replace('_', ' ').lower().strip()
                object_counts[normalized_obj] = object_counts.get(normalized_obj, 0) + 1

            # 按出現頻率排序,返回前三個主要物件
            sorted_objects = sorted(object_counts.items(), key=lambda x: x[1], reverse=True)
            return [obj[0] for obj in sorted_objects[:3]]

        except Exception as e:
            logger.warning(f"Error analyzing primary objects: {str(e)}")
            return []

    def _enhance_zone_description(self, original_description: str, zone_data: Dict) -> str:
        """
        增強區域描述的自然性和完整性
        """
        try:
            if not original_description or not original_description.strip():
                return self._generate_fallback_description(zone_data)

            import re
            enhanced = original_description.strip()

            # 改善技術性表達為自然語言
            enhanced = re.sub(r'\bin central direction\b', 'in the center', enhanced)
            enhanced = re.sub(r'\bin west area\b', 'on the left side', enhanced)
            enhanced = re.sub(r'\bin east direction\b', 'on the right side', enhanced)
            enhanced = re.sub(r'\bnear traffic signals\b', 'near the traffic lights', enhanced)
            enhanced = re.sub(r'\bwith (\d+) (\w+)\b', r'where \1 \2 can be seen', enhanced)

            # 移除重複和冗餘表達
            enhanced = re.sub(r'\barea with.*?in.*?area\b', lambda m: m.group(0).split(' in ')[0], enhanced)
            enhanced = enhanced.replace('traffic area', 'area').replace('crossing area', 'crossing')

            # 標準化描述結構
            if enhanced.startswith('Pedestrian'):
                enhanced = re.sub(r'^Pedestrian crossing area', 'The main pedestrian crossing', enhanced)
            elif enhanced.startswith('Vehicle'):
                enhanced = re.sub(r'^Vehicle traffic area', 'The vehicle movement area', enhanced)
            elif enhanced.startswith('Traffic control'):
                enhanced = re.sub(r'^Traffic control area', 'Traffic management elements', enhanced)

            # 移除內部標識符格式
            enhanced = re.sub(r'\b\w+_\w+(?:_\w+)*\b', lambda m: m.group(0).replace('_', ' '), enhanced)

            # 確保描述的完整性
            if not enhanced.endswith('.'):
                enhanced += '.'

            # 改善描述的自然性
            enhanced = enhanced.replace('with with', 'with')
            enhanced = re.sub(r'\s{2,}', ' ', enhanced)

            return enhanced

        except Exception as e:
            logger.warning(f"Error enhancing zone description: {str(e)}")
            return original_description if original_description else "A functional area within the scene."

    def _generate_fallback_description(self, zone_data: Dict) -> str:
        """
        為缺少描述的區域生成備用描述

        Args:
            zone_data: 區域數據

        Returns:
            str: 備用描述
        """
        try:
            objects = zone_data.get("objects", [])
            region = zone_data.get("region", "")

            if objects:
                object_count = len(objects)
                unique_objects = list(set(objects))

                if object_count == 1:
                    return f"Area containing {unique_objects[0].replace('_', ' ')}."
                elif len(unique_objects) <= 3:
                    obj_list = ", ".join([obj.replace('_', ' ') for obj in unique_objects])
                    return f"Area featuring {obj_list}."
                else:
                    return f"Multi-functional area with {object_count} elements including various objects."

            return "Functional area within the scene."

        except Exception as e:
            logger.warning(f"Error generating fallback description: {str(e)}")
            return "Activity area."

    def _build_category_regions_mapping(self, detected_objects: List[Dict]) -> Dict:
        """
        建立物件按類別和區域的分組映射

        Args:
            detected_objects: 檢測到的物件列表

        Returns:
            按類別和區域分組的物件字典
        """
        try:
            category_regions = {}

            for obj in detected_objects:
                category = self._categorize_object(obj)
                if not category:
                    continue

                if category not in category_regions:
                    category_regions[category] = {}

                region = obj.get("region", "center")
                if region not in category_regions[category]:
                    category_regions[category][region] = []

                category_regions[category][region].append(obj)

            logger.debug(f"Built category regions mapping with {len(category_regions)} categories")
            return category_regions

        except Exception as e:
            logger.error(f"Error building category regions mapping: {str(e)}")
            logger.error(traceback.format_exc())
            return {}

    def _categorize_object(self, obj: Dict) -> str:
        """
        將檢測到的物件分類到功能類別中,用於區域識別
        確保所有返回值都使用自然語言格式,避免底線或技術性標識符
        """
        try:
            class_id = obj.get("class_id", -1)
            class_name = obj.get("class_name", "").lower().strip()

            # 優先處理 traffic light
            # 只要 class_id == 9 或 class_name 包含 "traffic light",就分類為 "traffic light"
            if class_id == 9 or "traffic light" in class_name:
                return "traffic light"

            # 如果有自訂的 OBJECT_CATEGORIES 映射,優先使用它
            if hasattr(self, 'OBJECT_CATEGORIES') and self.OBJECT_CATEGORIES:
                for category, ids in self.OBJECT_CATEGORIES.items():
                    if class_id in ids:
                        # 確保返回的類別名稱使用自然語言格式
                        return self._clean_category_name(category)

            # COCO class default name
            furniture_items = ["chair", "couch", "bed", "dining table", "toilet"]
            plant_items = ["potted plant"]
            electronic_items = ["tv", "laptop", "mouse", "remote", "keyboard", "cell phone"]
            vehicle_items = ["bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat"]
            person_items = ["person"]
            kitchen_items = [
                "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl",
                "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog",
                "pizza", "donut", "cake", "refrigerator", "oven", "toaster", "sink", "microwave"
            ]
            sports_items = [
                "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
                "baseball glove", "skateboard", "surfboard", "tennis racket"
            ]
            personal_items = ["handbag", "tie", "suitcase", "umbrella", "backpack"]

            # fallback natural language
            if any(item in class_name for item in furniture_items):
                return "furniture"
            elif any(item in class_name for item in plant_items):
                return "plant"
            elif any(item in class_name for item in electronic_items):
                return "electronics"
            elif any(item in class_name for item in vehicle_items):
                return "vehicle"
            elif any(item in class_name for item in person_items):
                return "person"
            elif any(item in class_name for item in kitchen_items):
                return "kitchen items"  # 移除底線
            elif any(item in class_name for item in sports_items):
                return "sports"
            elif any(item in class_name for item in personal_items):
                return "personal items"  # 移除底線
            else:
                return "misc"

        except Exception as e:
            logger.error(f"Error categorizing object: {str(e)}")
            logger.error(traceback.format_exc())
            return "misc"

    def _clean_category_name(self, category: str) -> str:
        """
        清理類別名稱,移除底線並轉換為較自然的格式

        Args:
            category: 原始類別名稱

        Returns:
            str: 清理後的類別名稱
        """
        try:
            if not category:
                return "misc"

            # 將底線替換為空格
            cleaned = category.replace('_', ' ')

            # 處理常見的技術性命名模式
            replacements = {
                'kitchen items': 'kitchen items',
                'personal items': 'personal items',
                'traffic light': 'traffic light',
                'misc items': 'misc'
            }

            # 應用特定的替換規則
            for old_term, new_term in replacements.items():
                if cleaned == old_term:
                    return new_term

            return cleaned.strip()

        except Exception as e:
            logger.warning(f"Error cleaning category name '{category}': {str(e)}")
            return "misc"

    def _identify_default_zones(self, category_regions: Dict, detected_objects: List[Dict]) -> Dict:
        """
        當沒有匹配到特定場景類型時的一般功能區域識別

        Args:
            category_regions: 按類別和區域分組的物件字典
            detected_objects: 檢測到的物件列表

        Returns:
            預設功能區域字典
        """
        try:
            zones = {}

            # 按類別分組物件並找到主要集中區域
            for category, regions in category_regions.items():
                if not regions:
                    continue

                # 找到此類別中物件最多的區域
                main_region = max(regions.items(),
                            key=lambda x: len(x[1]),
                            default=(None, []))

                if main_region[0] is None or len(main_region[1]) < 2:
                    continue

                # 創建基於物件類別的區域
                zone_objects = [obj["class_name"] for obj in main_region[1]]

                # 如果物件太少,跳過
                if len(zone_objects) < 2:
                    continue

                # 根據類別創建區域名稱和描述
                if category == "furniture":
                    zones["furniture arrangement area"] = {
                        "region": main_region[0],
                        "objects": zone_objects,
                        "description": f"Furniture arrangement area featuring {self._format_object_list_naturally(zone_objects[:3])}"
                    }
                elif category == "electronics":
                    zones["electronics area"] = {
                        "region": main_region[0],
                        "objects": zone_objects,
                        "description": f"Electronics area containing {self._format_object_list_naturally(zone_objects[:3])}"
                    }
                elif category == "kitchen_items":
                    zones["dining_zone"] = {
                        "region": main_region[0],
                        "objects": zone_objects,
                        "description": f"Dining or food area with {', '.join(zone_objects[:3])}"
                    }
                elif category == "vehicle":
                    zones["vehicle_zone"] = {
                        "region": main_region[0],
                        "objects": zone_objects,
                        "description": f"Area with vehicles including {', '.join(zone_objects[:3])}"
                    }
                elif category == "personal_items":
                    zones["personal_items_zone"] = {
                        "region": main_region[0],
                        "objects": zone_objects,
                        "description": f"Area with personal items including {', '.join(zone_objects[:3])}"
                    }

            # 檢查人群聚集
            people_objs = [obj for obj in detected_objects if obj["class_id"] == 0]
            if len(people_objs) >= 2:
                people_regions = {}
                for obj in people_objs:
                    region = obj["region"]
                    if region not in people_regions:
                        people_regions[region] = []
                    people_regions[region].append(obj)

                if people_regions:
                    main_people_region = max(people_regions.items(),
                                        key=lambda x: len(x[1]),
                                        default=(None, []))

                    if main_people_region[0] is not None:
                        zones["people_zone"] = {
                            "region": main_people_region[0],
                            "objects": ["person"] * len(main_people_region[1]),
                            "description": f"Area with {len(main_people_region[1])} people"
                        }

            logger.debug(f"Identified {len(zones)} default zones")
            return zones

        except Exception as e:
            logger.error(f"Error identifying default zones: {str(e)}")
            logger.error(traceback.format_exc())
            return {}

    def _format_object_list_naturally(self, object_list: List[str]) -> str:
        """
        將物件列表格式化為自然語言表達

        Args:
            object_list: 物件名稱列表

        Returns:
            str: 自然語言格式的物件列表
        """
        try:
            if not object_list:
                return "various items"

            # 標準化物件名稱
            normalized_objects = []
            for obj in object_list:
                normalized = obj.replace('_', ' ').strip()
                if normalized:
                    normalized_objects.append(normalized)

            if not normalized_objects:
                return "various items"

            # 格式化列表
            if len(normalized_objects) == 1:
                return normalized_objects[0]
            elif len(normalized_objects) == 2:
                return f"{normalized_objects[0]} and {normalized_objects[1]}"
            else:
                return ", ".join(normalized_objects[:-1]) + f", and {normalized_objects[-1]}"

        except Exception as e:
            logger.warning(f"Error formatting object list naturally: {str(e)}")
            return "various items"

    def _create_basic_zones_from_objects(self, detected_objects: List[Dict], scene_type: str) -> Dict:
        """
        從個別高置信度物件創建基本功能區域
        這是標準區域識別失敗時的後備方案

        Args:
            detected_objects: 檢測到的物件列表
            scene_type: 場景類型

        Returns:
            基本區域字典
        """
        try:
            zones = {}

            # 專注於高置信度物件
            high_conf_objects = [obj for obj in detected_objects if obj.get("confidence", 0) >= 0.6]

            if not high_conf_objects:
                high_conf_objects = detected_objects  # 後備到所有物件

            # 根據個別重要物件創建區域
            processed_objects = set()  # 避免重複處理相同類型的物件

            for obj in high_conf_objects[:3]:  # 限制為前3個物件
                class_name = obj["class_name"]
                region = obj.get("region", "center")

                # 避免為同一類型物件創建多個區域
                if class_name in processed_objects:
                    continue
                processed_objects.add(class_name)

                # 基於物件類型創建描述性區域
                zone_description = self._get_basic_zone_description(class_name, scene_type)
                descriptive_key = self._generate_object_based_zone_key(class_name, region)

                if zone_description and descriptive_key:
                    zones[descriptive_key] = {
                        "region": region,
                        "objects": [class_name],
                        "description": zone_description
                    }

            logger.debug(f"Created {len(zones)} basic zones from high confidence objects")
            return zones

        except Exception as e:
            logger.error(f"Error creating basic zones from objects: {str(e)}")
            logger.error(traceback.format_exc())
            return {}

    def _generate_object_based_zone_key(self, class_name: str, region: str) -> str:
        """
        基於物件類型和位置生成描述性的區域鍵名

        Args:
            class_name: 物件類別名稱
            region: 區域位置

        Returns:
            str: 描述性區域鍵名
        """
        try:
            # 標準化物件名稱
            normalized_class = class_name.replace('_', ' ').lower().strip()

            # 物件類型對應的區域描述
            object_zone_mapping = {
                'person': 'activity area',
                'car': 'vehicle area',
                'truck': 'vehicle area',
                'bus': 'vehicle area',
                'motorcycle': 'vehicle area',
                'bicycle': 'cycling area',
                'traffic light': 'traffic control area',
                'chair': 'seating area',
                'sofa': 'seating area',
                'bed': 'rest area',
                'dining table': 'dining area',
                'tv': 'entertainment area',
                'laptop': 'workspace area',
                'potted plant': 'decorative area'
            }

            base_description = object_zone_mapping.get(normalized_class, f"{normalized_class} area")

            # 添加位置信息以提供更具體的描述
            position_modifiers = {
                'top_left': 'upper left',
                'top_center': 'upper central',
                'top_right': 'upper right',
                'middle_left': 'left side',
                'middle_center': 'central',
                'middle_right': 'right side',
                'bottom_left': 'lower left',
                'bottom_center': 'lower central',
                'bottom_right': 'lower right'
            }

            if region in position_modifiers:
                return f"{position_modifiers[region]} {base_description}"

            return base_description

        except Exception as e:
            logger.warning(f"Error generating object-based zone key for '{class_name}': {str(e)}")
            return "activity area"

    def _get_basic_zone_description(self, class_name: str, scene_type: str) -> str:
        """
        基於物件和場景類型生成基本區域描述

        Args:
            class_name: 物件類別名稱
            scene_type: 場景類型

        Returns:
            區域描述字串
        """
        try:
            descriptions = {
                "bed": "Sleeping and rest area",
                "sofa": "Seating and relaxation area",
                "chair": "Seating area",
                "dining table": "Dining and meal area",
                "tv": "Entertainment and media area",
                "laptop": "Work and computing area",
                "potted plant": "Decorative and green space area",
                "car": "Vehicle and transportation area",
                "person": "Activity and social area"
            }

            # 只有在明確的廚房場景中才使用廚房描述
            kitchen_related_objects = ["refrigerator", "microwave", "oven", "sink", "dishwasher", "stove"]

            if class_name in kitchen_related_objects:
                # 檢查場景類型是否真的是廚房相關
                kitchen_scene_types = ["kitchen", "professional_kitchen", "cooking_area"]

                if scene_type in kitchen_scene_types:
                    # 只有在明確的廚房場景中才使用廚房描述
                    if class_name == "refrigerator":
                        descriptions[class_name] = "Food storage and kitchen area"
                    elif class_name == "microwave":
                        descriptions[class_name] = "Food preparation area"
                    elif class_name == "oven":
                        descriptions[class_name] = "Cooking area"
                    elif class_name == "sink":
                        descriptions[class_name] = "Washing and preparation area"
                    else:
                        descriptions[class_name] = "Kitchen appliance area"
                else:
                    # === 修正:非廚房場景中的廚房物件使用中性描述 ===
                    # 在餐廳、客廳等場景中,即使檢測到這些物件也不使用廚房描述
                    if class_name == "refrigerator":
                        descriptions[class_name] = "Storage area"
                    elif class_name == "microwave":
                        descriptions[class_name] = "Appliance area"
                    elif class_name == "oven":
                        descriptions[class_name] = "Equipment area"
                    elif class_name == "sink":
                        descriptions[class_name] = "Utility area"
                    else:
                        descriptions[class_name] = "Equipment area"

            return descriptions.get(class_name, f"Functional area with {class_name}")

        except Exception as e:
            logger.error(f"Error getting basic zone description for '{class_name}': {str(e)}")
            return f"Functional area with {class_name}"


    def _generate_category_fallback_zones(self, all_detected_objects: List[Dict], current_zones: Dict) -> Dict:
        """
        通用 fallback:針對 all_detected_objects 裡,每一個 (class_name, region) 組合是否已經
        在 current_zones 裡出現過。如果還沒,就為它們產生一個 fallback zone。
        """
        general_fallback = {
                0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus',
                6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant',
                11: 'stop sign', 12: 'parking meter', 13: 'bench', 14: 'bird', 15: 'cat',
                16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant', 21: 'bear',
                22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella', 26: 'handbag',
                27: 'tie', 28: 'suitcase', 29: 'frisbee', 30: 'skis', 31: 'snowboard',
                32: 'sports ball', 33: 'kite', 34: 'baseball bat', 35: 'baseball glove',
                36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle',
                40: 'wine glass', 41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl',
                46: 'banana', 47: 'apple', 48: 'sandwich', 49: 'orange', 50: 'broccoli',
                51: 'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut', 55: 'cake', 56: 'chair',
                57: 'couch', 58: 'potted plant', 59: 'bed', 60: 'dining table', 61: 'toilet',
                62: 'tv', 63: 'laptop', 64: 'mouse', 65: 'remote', 66: 'keyboard',
                67: 'cell phone', 68: 'microwave', 69: 'oven', 70: 'toaster', 71: 'sink',
                72: 'refrigerator', 73: 'book', 74: 'clock', 75: 'vase', 76: 'scissors',
                77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'

        }

        # 1. 統計 current_zones 裡,已使用掉的 (class_name, region) 次數
        used_count = {}
        for zone_info in current_zones.values():
            rg = zone_info.get("region", "")
            for obj_name in zone_info.get("objects", []):
                key = (obj_name, rg)
                used_count[key] = used_count.get(key, 0) + 1

        # 2. 統計 all_detected_objects 裡的 (class_name, region) 總次數
        total_count = {}
        for obj in all_detected_objects:
            cname = obj.get("class_name", "")
            rg = obj.get("region", "")
            key = (cname, rg)
            total_count[key] = total_count.get(key, 0) + 1

        # 3. 把 default_classes 轉換成「class_name → fallback 區域 type」的對照表
        category_to_fallback = {
            # 行人與交通工具
            "person":        "pedestrian area",
            "bicycle":       "vehicle movement area",
            "car":           "vehicle movement area",
            "motorcycle":    "vehicle movement area",
            "airplane":      "vehicle movement area",
            "bus":           "vehicle movement area",
            "train":         "vehicle movement area",
            "truck":         "vehicle movement area",
            "boat":          "vehicle movement area",
            "traffic light": "traffic control area",
            "fire hydrant":  "traffic control area",
            "stop sign":     "traffic control area",
            "parking meter": "traffic control area",
            "bench":         "public furniture area",

            # 動物類、鳥類
            "bird":          "animal area",
            "cat":           "animal area",
            "dog":           "animal area",
            "horse":         "animal area",
            "sheep":         "animal area",
            "cow":           "animal area",
            "elephant":      "animal area",
            "bear":          "animal area",
            "zebra":         "animal area",
            "giraffe":       "animal area",

            # 托運與行李
            "backpack":      "personal items area",
            "umbrella":      "personal items area",
            "handbag":       "personal items area",
            "tie":           "personal items area",
            "suitcase":      "personal items area",

            # 運動器材
            "frisbee":       "sports area",
            "skis":          "sports area",
            "snowboard":     "sports area",
            "sports ball":   "sports area",
            "kite":          "sports area",
            "baseball bat":  "sports area",
            "baseball glove":"sports area",
            "skateboard":    "sports area",
            "surfboard":     "sports area",
            "tennis racket": "sports area",

            # 餐具與用餐相關物品重新歸類為 dining area
            "bottle":        "dining area",
            "wine glass":    "dining area",
            "cup":           "dining area",
            "fork":          "dining area",
            "knife":         "dining area",
            "spoon":         "dining area",
            "bowl":          "dining area",
            "dining table":  "dining area",  # 確保 dining table 也歸類為 dining area

            # 食品使用中性的 food area
            "banana":        "food area",
            "apple":         "food area",
            "sandwich":      "food area",
            "orange":        "food area",
            "broccoli":      "food area",
            "carrot":        "food area",
            "hot dog":       "food area",
            "pizza":         "food area",
            "donut":         "food area",
            "cake":          "food area",

            # 只有在有明確的廚房設備才使用 kitchen area
            "refrigerator":  "kitchen appliance area",
            "oven":          "kitchen appliance area",
            "microwave":     "kitchen appliance area",
            "toaster":       "kitchen appliance area",
            "sink":          "kitchen appliance area",

            # 其他物品
            "book":          "miscellaneous area",
            "clock":         "miscellaneous area",
            "vase":          "decorative area",
            "scissors":      "miscellaneous area",
            "teddy bear":    "miscellaneous area",
            "hair drier":    "miscellaneous area",
            "toothbrush":    "miscellaneous area",

            # 電子產品
            "tv":            "electronics area",
            "laptop":        "electronics area",
            "mouse":         "electronics area",
            "remote":        "electronics area",
            "keyboard":      "electronics area",
            "cell phone":    "electronics area",

            # 家具類
            "chair":         "furniture arrangement area",
            "couch":         "furniture arrangement area",
            "bed":           "furniture arrangement area",
            "toilet":        "furniture arrangement area",

            # 植物(室內植物或戶外綠化)
            "potted plant":  "decorative area",
        }

        # 4. 計算缺少的 (class_name, region) 並建立 fallback zone
        for (cname, rg), total in total_count.items():
            used = used_count.get((cname, rg), 0)
            missing = total - used
            if missing <= 0:
                continue

            # (A) 決定這個 cname 在 fallback 裡屬於哪個大 class(zone_type)
            zone_type = category_to_fallback.get(cname, "miscellaneous area")

            # (B) 根據 region 與 zone_type 組合成 fallback_key
            fallback_key = f"{rg} {zone_type}"

            # (C) 如果名稱重複,就在後面加 (1),(2),… 避免掉衝突
            if fallback_key in current_zones or fallback_key in general_fallback:
                suffix = 1
                new_key = f"{fallback_key} ({suffix})"
                while new_key in current_zones or new_key in general_fallback:
                    suffix += 1
                    new_key = f"{fallback_key} ({suffix})"
                fallback_key = new_key

            # (D) 建立這支 fallback zone,objects 裡放 missing 個 cname
            general_fallback[fallback_key] = {
                "region": rg,
                "objects": [cname] * missing,
                "description": f"{missing} {cname}(s) placed in fallback {zone_type} for region {rg}"
            }

        return general_fallback