"""
同步系统工具函数模块

提供业务键提取等通用功能。
"""
from typing import List, Tuple, Optional, Any, Dict
import logging

logger = logging.getLogger(__name__)


def is_id_field(field_name: str) -> bool:
    """
    判断字段是否为ID字段。
    
    ID字段的判断规则：
    - 以 _id 结尾（如 project_id, company_id）
    - 字段名为 id
    
    Args:
        field_name: 字段名
    
    Returns:
        如果是ID字段返回True
    """
    return field_name.endswith("_id") or field_name == "id"


def extract_biz_key_dict(
    data: Any,
    field_names: List[str]
) -> Optional[Dict[str, str]]:
    """
    从数据对象提取业务键字段，返回字典格式。
    
    Args:
        data: 数据对象（dict或pydantic model）
        field_names: 业务键字段名列表
    
    Returns:
        业务键字段字典，如果任何必需字段缺失则返回None
    """
    if not field_names or not data:
        return None
    
    # 转换为字典
    if isinstance(data, dict):
        d = data
    else:
        d = data.model_dump()
    
    key_dict = {}
    for field_name in field_names:
        # 区分：字段不存在 vs 字段存在但值为None
        if field_name not in d:
            return None  # 字段不存在，视为缺失
        value = d.get(field_name)
        # 值为None时保留为空字符串，允许作为有效业务键值
        key_dict[field_name] = str(value) if value is not None else ""
    
    return key_dict if key_dict else None


def dict_to_biz_key_tuple(
    key_dict: Dict[str, str],
    field_names: List[str]
) -> Tuple:
    """
    将业务键字典转换为tuple（按field_names顺序）。
    
    Args:
        key_dict: 业务键字段字典
        field_names: 字段名顺序
    
    Returns:
        业务键tuple
    """
    return tuple(key_dict[fn] for fn in field_names)


async def resolve_id_fields_in_key_dict(
    key_dict: Dict[str, str],
    id_resolver,
    node_type_hints: Dict[str, str]
) -> tuple[Optional[Dict[str, str]], Optional[str]]:
    """
    解析业务键字典中的ID字段，将本地ID转换为远程ID。
    
    只处理ID字段（以_id结尾或为id），其他字段保持不变。
    
    特殊处理：
    - 如果 ID 字段值为空字符串 ""，直接保留（空值也是有效的业务键值）
    - 只有非空 ID 才需要解析
    
    Args:
        key_dict: 业务键字典
        id_resolver: ID解析器实例
        node_type_hints: 字段名到node_type的映射
    
    Returns:
        (resolved_dict, error_msg): 成功时返回 (解析后的字典, None)，失败时返回 (None, 错误描述)
    """
    resolved_dict = {}
    
    for field_name, value in key_dict.items():
        if is_id_field(field_name):
            # 这是ID字段
            if value == "" or value is None:
                # 空值直接保留，不尝试解析
                # 空值也是有效的业务键值，只要两边一致就能匹配
                resolved_dict[field_name] = value or ""
            else:
                # 非空ID需要解析
                node_type = node_type_hints.get(field_name)
                remote_id = await id_resolver.resolve_id(
                    value, node_type_hint=node_type
                )
                if remote_id is None:
                    # ID解析失败，返回详细错误信息
                    node_type_info = f"({node_type})" if node_type else "(未知类型)"
                    error_msg = f"字段 {field_name}{node_type_info} 的 ID '{value}' 解析失败（依赖节点未绑定）"
                    return None, error_msg
                resolved_dict[field_name] = remote_id
        else:
            # 非ID字段，直接使用原值
            resolved_dict[field_name] = value
    
    return resolved_dict, None
