"""TypeSpec, SymbolMeta, SymbolKind — CTypeInfo 的拆分类型

Phase 1 重构：将 CTypeInfo 的 40+ 平铺字段拆分为三个聚焦的类型：
- TypeSpec:   纯类型描述（BaseType + 指针 + 限定符 + 数组维度等）
- SymbolMeta: 符号表元数据（名称、行号、文件、类型种类、成员等）
- SymbolKind: 枚举类型种类（从 is_xxx bool 字段派生，供新代码使用）

设计原则：
- CTypeInfo 内部组合 TypeSpec + SymbolMeta
- 旧 property 委托到新字段，外部代码零修改
- 渐进式迁移：先加新字段，后删旧字段
- 类型种类 bool 保持独立（因为 IsTypedef 和 IsStruct 可以同时为 True）
- SymbolKind 从 is_xxx bool 字段派生，供新代码使用
"""
from __future__ import annotations

import enum
from typing import TYPE_CHECKING, List, Dict, Tuple, Any, Optional

if TYPE_CHECKING:
    from lib.core.Handles.HandlesBase import CTypeInfo

from lib.includes import t


class SymbolKind(enum.Enum):
    """符号类型种类 — 从 is_xxx bool 字段派生的主类型

    注意：IsTypedef 与 IsStruct/IsEnum/IsUnion 正交（可以同时为 True），
    因此 SymbolKind 只反映"主类型"，IsTypedef 需要单独查询。
    """
    UNKNOWN = 0
    VARIABLE = 1
    FUNCTION = 2
    STRUCT = 3
    UNION = 4
    ENUM = 5
    DEFINE = 6
    ENUM_MEMBER = 7
    MODULE = 8
    EXCEPTION = 9
    RENUM = 10
    FUNC_PTR = 11
    STATE = 12
    CPYTHON_OBJECT = 13


# CTypeInfo 旧字段 → (目标, 新字段名) 的路由表
# 目标: 'ts' = TypeSpec, 'sm' = SymbolMeta
FIELD_ROUTES = {
    # --- TypeSpec 字段 ---
    'PtrCount':       ('ts', 'ptr_count'),
    'VarConst':       ('ts', 'var_const'),
    'VarVolatile':    ('ts', 'var_volatile'),
    'DataConst':      ('ts', 'data_const'),
    'DataVolatile':   ('ts', 'data_volatile'),
    'ArrayDims':      ('ts', 'array_dims'),
    'Storage':        ('ts', 'storage'),
    'IsFuncPtr':      ('ts', 'is_func_ptr'),
    'FuncPtrParams':  ('ts', 'func_ptr_params'),
    'FuncParamNames': ('ts', 'func_param_names'),
    'FuncPtrReturn':  ('ts', 'func_ptr_return'),
    'IsVariadic':     ('ts', 'is_variadic'),
    'IsBitField':     ('ts', 'is_bitfield'),
    'BitWidth':       ('ts', 'bit_width'),
    'ByteOrder':      ('ts', 'byte_order'),
    'IsArrayPtr':     ('ts', 'is_array_ptr'),
    'ArrayPtr':       ('ts', 'array_ptr'),
    'IsState':        ('ts', 'is_state'),
    'OriginalType':   ('ts', 'original_type'),
    'IsSigned':       ('ts', 'is_signed'),

    # --- SymbolMeta 字段 ---
    'Name':           ('sm', 'name'),
    'Lineno':         ('sm', 'lineno'),
    'file':           ('sm', 'file'),
    'ModuleName':     ('sm', 'module_name'),
    'Members':        ('sm', 'members'),
    'IsCpythonObject':('sm', 'is_cpython_object'),
    'IsPacked':       ('sm', 'is_packed'),
    'IsAnonymous':    ('sm', 'is_anonymous'),
    'IsInline':       ('sm', 'is_inline'),
    'InlineBody':     ('sm', 'inline_body'),
    'InlineParams':   ('sm', 'inline_params'),
    'RenumVariants':  ('sm', 'renum_variants'),
    'DeclaredType':   ('sm', 'declared_type'),
    'CreturnTypes':   ('sm', 'creturn_types'),
    'MetaList':       ('sm', 'meta_list'),
    'IsModuleAlias':  ('sm', 'is_module_alias'),
    'ResolvedModule': ('sm', 'resolved_module'),
    'DefineValue':    ('sm', 'define_value'),
    'EnumName':       ('sm', 'enum_name'),
    'value':          ('sm', 'enum_value'),

    # --- 类型种类 bool（直接存储在 SymbolMeta 的 __slots__ 字段）---
    'IsStruct':         ('sm', 'is_struct'),
    'IsEnum':           ('sm', 'is_enum'),
    'IsUnion':          ('sm', 'is_union'),
    'IsTypedef':        ('sm', 'is_typedef'),
    'IsVariable':       ('sm', 'is_variable'),
    'IsFunction':       ('sm', 'is_function'),
    'IsDefine':         ('sm', 'is_define'),
    'IsEnumMember':     ('sm', 'is_enum_member'),
    'IsRenum':          ('sm', 'is_renum'),
    'IsExceptionClass': ('sm', 'is_exception_class'),

    # --- _extra（CTypeInfo 旧 _extra 字典，迁移到 SymbolMeta）---
    '_extra':           ('sm', '_extra'),
}


class TypeSpec:
    """纯类型描述 — 不包含符号表元数据

    职责：描述一个 C 类型的结构（基础类型、指针层数、限定符、数组维度等）
    不包含：名称、行号、文件路径、符号种类等元数据（这些归 SymbolMeta）

    注意：当前阶段保持与 CTypeInfo 旧字段的兼容性，
    PtrCount/VarConst/DataConst 等仍然使用扁平字段。
    未来 Phase 2 会将指针改为嵌套 PointerLayer 表示。
    """

    __slots__ = (
        '_base_type', 'ptr_count',
        'var_const', 'var_volatile', 'data_const', 'data_volatile',
        'array_dims', 'storage',
        'is_func_ptr', 'func_ptr_params', 'func_param_names', 'func_ptr_return',
        'is_variadic',
        'is_bitfield', 'bit_width',
        'byte_order',
        'is_array_ptr', 'array_ptr',
        'is_state',
        'original_type',
        'is_signed',
    )

    def __init__(self):
        self._base_type: t.CType | tuple | None = None          # t.CType 实例或 tuple
        self.ptr_count: int = 0
        self.var_const: bool = False
        self.var_volatile: bool = False
        self.data_const: bool = False
        self.data_volatile: bool = False
        self.array_dims: List[str] = []
        self.storage: t.CType | None = None             # t.CType (CStatic/CExtern/CExport 等)
        self.is_func_ptr: bool = False
        self.func_ptr_params: List[Tuple[str, CTypeInfo]] = []   # (参数名, CTypeInfo)
        self.func_param_names: List[str] = []
        self.func_ptr_return: CTypeInfo | None = None     # CTypeInfo
        self.is_variadic: bool = False
        self.is_bitfield: bool = False
        self.bit_width: int = 0
        self.byte_order: str = ""            # "big", "little", or ""
        self.is_array_ptr: bool = False
        self.array_ptr: CTypeInfo | None = None           # CTypeInfo
        self.is_state: bool = False
        self.original_type: CTypeInfo | str | None = None       # CTypeInfo | str | None (typedef 原始类型)
        self.is_signed: Optional[bool] = None  # None = 未设置, True/False = 有符号/无符号

    @property
    def base_type(self) -> t.CType | tuple | None:
        return self._base_type

    @base_type.setter
    def base_type(self, value: t.CType | tuple | None):
        """设置 BaseType，与 CTypeInfo.BaseType setter 逻辑一致（不含 kind 副作用）"""
        if value is None:
            self._base_type = None
            return

        if isinstance(value, (tuple, list)):
            self._base_type = tuple(value)
            return

        if isinstance(value, type) and issubclass(value, t.CType):
            self._base_type = value()
            return

        if isinstance(value, t.CType):
            self._base_type = value
            return

        raise TypeError(
            f"base_type must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}"
        )

    def copy(self) -> TypeSpec:
        """深拷贝"""
        new: TypeSpec = TypeSpec()
        new._base_type = self._base_type
        new.ptr_count = self.ptr_count
        new.var_const = self.var_const
        new.var_volatile = self.var_volatile
        new.data_const = self.data_const
        new.data_volatile = self.data_volatile
        new.array_dims = list(self.array_dims)
        new.storage = self.storage
        new.is_func_ptr = self.is_func_ptr
        new.func_ptr_params = list(self.func_ptr_params)
        new.func_param_names = list(self.func_param_names)
        new.func_ptr_return = self.func_ptr_return
        new.is_variadic = self.is_variadic
        new.is_bitfield = self.is_bitfield
        new.bit_width = self.bit_width
        new.byte_order = self.byte_order
        new.is_array_ptr = self.is_array_ptr
        new.array_ptr = self.array_ptr
        new.is_state = self.is_state
        new.original_type = self.original_type
        new.is_signed = self.is_signed
        return new


class SymbolMeta:
    """符号表条目的元数据 — 与类型描述无关

    职责：记录符号的名称、位置、种类、成员等元数据
    不包含：类型结构（BaseType、指针、限定符等，这些归 TypeSpec）

    is_struct/is_enum/is_union/is_typedef/is_variable/is_function/is_define/
    is_enum_member/is_renum/is_exception_class: 独立 bool 字段，存储类型种类。
    这些 flag 不是互斥的（IsTypedef 和 IsStruct 可以同时为 True）。
    SymbolKind 从这些 bool 字段派生，供新代码使用。
    """

    __slots__ = (
        'name', 'lineno', 'file', 'module_name',
        'members',
        'is_cpython_object', 'is_packed',
        'define_value',
        'enum_name', 'enum_value',
        'is_inline', 'inline_body', 'inline_params',
        'is_anonymous',
        'renum_variants',
        'declared_type', 'creturn_types',
        'meta_list',
        'is_module_alias', 'resolved_module',
        'is_struct', 'is_enum', 'is_union', 'is_typedef',
        'is_variable', 'is_function', 'is_define',
        'is_enum_member', 'is_renum', 'is_exception_class',
        '_extra',
    )

    def __init__(self):
        self.name: str = ""
        self.lineno: int = 0
        self.file: str = ""
        self.module_name: str = ""
        self.members: Dict[str, CTypeInfo] = {}       # 成员名 -> CTypeInfo
        self.is_cpython_object: bool = False
        self.is_packed: bool = False
        self.define_value: int | str | float | bool | None = None
        self.enum_name: str = ""              # 枚举成员所属的枚举类名
        self.enum_value: int | None = None           # 枚举成员的值
        self.is_inline: bool = False
        self.inline_body: list | None = None
        self.inline_params: list | None = None
        self.is_anonymous: bool = False
        self.renum_variants: list = []
        self.declared_type: str = ""
        self.creturn_types: list = []
        self.meta_list: Any = None               # FuncMeta
        self.is_module_alias: bool = False
        self.resolved_module: str | None = None
        self.is_struct: bool = False
        self.is_enum: bool = False
        self.is_union: bool = False
        self.is_typedef: bool = False
        self.is_variable: bool = False
        self.is_function: bool = False
        self.is_define: bool = False
        self.is_enum_member: bool = False
        self.is_renum: bool = False
        self.is_exception_class: bool = False
        self._extra: dict = {}

    @property
    def kind(self) -> SymbolKind:
        """从 is_xxx bool 字段派生主类型种类"""
        if self.is_struct or self.is_cpython_object:
            return SymbolKind.STRUCT if not self.is_cpython_object else SymbolKind.CPYTHON_OBJECT
        if self.is_enum:
            return SymbolKind.RENUM if self.is_renum else SymbolKind.ENUM
        if self.is_union:
            return SymbolKind.UNION
        if self.is_function:
            return SymbolKind.FUNCTION
        if self.is_variable:
            return SymbolKind.VARIABLE
        if self.is_define:
            return SymbolKind.DEFINE
        if self.is_enum_member:
            return SymbolKind.ENUM_MEMBER
        if self.is_exception_class:
            return SymbolKind.EXCEPTION
        return SymbolKind.UNKNOWN

    def copy(self) -> SymbolMeta:
        """深拷贝"""
        new: SymbolMeta = SymbolMeta()
        new.name = self.name
        new.lineno = self.lineno
        new.file = self.file
        new.module_name = self.module_name
        new.members = dict(self.members)
        new.is_cpython_object = self.is_cpython_object
        new.is_packed = self.is_packed
        new.define_value = self.define_value
        new.enum_name = self.enum_name
        new.enum_value = self.enum_value
        new.is_inline = self.is_inline
        new.inline_body = self.inline_body
        new.inline_params = list(self.inline_params) if self.inline_params else None
        new.is_anonymous = self.is_anonymous
        new.renum_variants = list(self.renum_variants)
        new.declared_type = self.declared_type
        new.creturn_types = list(self.creturn_types)
        new.meta_list = self.meta_list
        new.is_module_alias = self.is_module_alias
        new.resolved_module = self.resolved_module
        new.is_struct = self.is_struct
        new.is_enum = self.is_enum
        new.is_union = self.is_union
        new.is_typedef = self.is_typedef
        new.is_variable = self.is_variable
        new.is_function = self.is_function
        new.is_define = self.is_define
        new.is_enum_member = self.is_enum_member
        new.is_renum = self.is_renum
        new.is_exception_class = self.is_exception_class
        new._extra = dict(self._extra)
        return new
