from __future__ import annotations

import ast
from typing import Any, Callable, Dict, TYPE_CHECKING

from lib.core.Exportable import Exportable

if TYPE_CHECKING:
    import llvmlite.ir as ir

from lib.core.Handles import (
    IfHandle, ForHandle, WhileHandle,
    AnnAssignHandle,
    HandlesTypeMerge, ExprHandle, BodyHandle,
    ReturnHandle, AssignHandle, AugAssignHandle, DeleteHandle,
    WithHandle, TryHandle, AssertHandle, RaiseHandle, MatchHandle,
    ExprUtils, ExprOpsHandle, ExprAttrHandle, ExprBuiltinHandle,
    ExprAsmHandle, ExprFormatHandle, ExprLambdaHandle, ExprCallHandle,
    CSpecialCallHandle, TSpecialCallHandle,
    ClassHandle,
    FunctionHandle,
    ImportHandle
)
from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolTable         import SymbolTable
from lib.core.SymbolNode          import SymbolNode
from lib.constants.config         import mode as _ConfigMode
from lib.core.VLogger import get_logger as _vlog


def _StrictLog(logger: Callable[[str], None], msg: str) -> None:
    """在 strict 模式下记录异常日志"""
    if _ConfigMode == "strict":
        logger(msg)


class BaseTranslatorMixin:
    """代码转换器基础 Mixin

    提供 __init__、日志、调试输出与表达式处理等基础能力。
    """

    def __init__(self) -> None:
        self.VarScopes:           list[Dict[str, SymbolNode]] = [{}]  # 跟踪变量作用域，第一个是全局作用域
        self.FunctionReturnTypes: Dict[str, CTypeInfo] = {}  # 记录函数名和其返回类型
        self.CurrentCReturnTypes: list[CTypeInfo] | None = None  # 当前函数的 CReturn 类型列表
        self._CurrentCpythonObjectClass: str | None = None  # 当前正在处理的 CPython 对象类名
        self.FunctionDefCache:    dict = {}  # 函数定义缓存
        self.OriginalLines:       list[str] = []  # 原始代码行
        self.Content:             str = ''
        self.DebugFile:           str | None = None  # 调试输出文件路径
        self.IsHeader:            bool = False  # 是否生成头文件（仅处理定义、宏、导入等，忽略函数体）
        self.AnnotationModules:   set[str]  = set()  # 注解模块集合，用于识别类型定义模块
        self.Warnings:            list[str]  = []  # 警告日志
        self._ErrorStack: list[tuple[str, str, str]] = []  # 错误栈，按顺序收集错误位置
        self.Errors: list[dict[str, str | None]] = []  # 错误日志
        self.SliceCount: int = 0  # 切片计数
        self.SliceInfos: list = []  # 切片信息列表
        self.SliceLevel: int = 3  # 切片优化级别
        self.GeneratedTypes: set[str] = set()  # 在当前代码中生成的类型（struct/typedef）
        self.EmbeddedAssignments: dict[str, list] = {}  # {ClassName: [var1, var2, ...]} 嵌入的实例化变量
        self.TypedefAssignments: dict[str, list] = {}  # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量
        self.ChainAssignmentArrays: list = []  # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...]
        self.tree: ast.AST | None = None  # 保存解析后的 AST 树
        self.LibraryPaths: list[str] = ['.']  # 库搜索路径列表，默认包含当前目录
        self.InClass: bool = False  # 是否正在处理 class 定义
        self._UserTypeModules: dict = {}
        self._source_module_sig_files: dict = {}
        self._global_function_default_args: dict = {}
        self._global_function_param_names: dict = {}
        self.exception_registry: dict = {}
        self.exception_parents: dict = {}
        self._next_exception_code: int = 100
        # 以下属性原先在外部懒注入，此处显式初始化以避免 hasattr/getattr 动态反射
        self.config: Any = None
        self._ImportedModules: set[str] | None = None
        self._t_c_imported_names: dict = {}

        # 导出表
        self.Exportable         = Exportable(filename='')

        self.SymbolTable        = SymbolTable(self)
        self.IfHandler          = IfHandle(self)
        self.ForHandler         = ForHandle(self)
        self.WhileHandler       = WhileHandle(self)
        self.AnnAssignHandler   = AnnAssignHandle(self)
        self.TypeMergeHandler   = HandlesTypeMerge(self)
        self.ExprHandler        = ExprHandle(self)
        self.ExprUtils          = ExprUtils(self)
        self.ExprOpsHandle      = ExprOpsHandle(self)
        self.ExprAttrHandle     = ExprAttrHandle(self)
        self.ExprBuiltinHandle  = ExprBuiltinHandle(self)
        self.ExprAsmHandle      = ExprAsmHandle(self)
        self.ExprFormatHandle   = ExprFormatHandle(self)
        self.ExprLambdaHandle   = ExprLambdaHandle(self)
        self.ExprCallHandle     = ExprCallHandle(self)
        self.CSpecialCallHandle = CSpecialCallHandle(self)
        self.TSpecialCallHandle = TSpecialCallHandle(self)
        self.ClassHandler       = ClassHandle(self)
        self.FunctionHandler    = FunctionHandle(self)
        self.ImportHandler      = ImportHandle(self)
        self.BodyHandler        = BodyHandle(self)
        self.ReturnHandler      = ReturnHandle(self)
        self.AssignHandler      = AssignHandle(self)
        self.AugAssignHandler   = AugAssignHandle(self)
        self.DeleteHandler      = DeleteHandle(self)
        self.WithHandler        = WithHandle(self)
        self.TryHandler         = TryHandle(self)
        self.AssertHandler      = AssertHandle(self)
        self.RaiseHandler       = RaiseHandle(self)
        self.MatchHandler       = MatchHandle(self)

    def LogWarning(self, message: str, LineNum: int | None = None) -> None:
        """记录警告

        Args:
            message: 警告消息
            LineNum: 行号（可选）
        """
        warning = f"Warning: {message}"
        if LineNum is not None:
            warning += f" (line {LineNum})"
        self.Warnings.append(warning)

    def LogError(self, message: str, LineNum: int | None = None) -> None:
        """记录错误

        Args:
            message: 错误消息
            LineNum: 行号
        """
        _vlog().error(message)
        entry: dict[str, str | int | None] = {'message': message, 'line': LineNum}
        self.Errors.append(entry)

        # 检查 config 中是否有 debug 文件
        DebugFile: str | None = None
        if hasattr(self, 'config') and self.config:
            DebugFile = getattr(self.config, 'debug', None)

        if DebugFile:
            with open(DebugFile, 'a', encoding='utf-8') as f:
                LineInfo: str = f' line {LineNum}' if LineNum else ''
                f.write(f'[ERROR]{LineInfo}: {message}\n')

    def SetDebugFile(self, FilePath: str) -> None:
        """设置调试输出文件"""
        self.DebugFile = FilePath

    def DebugPrint(self, *args: Any, **kwargs: Any) -> None:
        """输出调试信息到文件"""
        if self.DebugFile:
            with open(self.DebugFile, 'a', encoding='utf-8') as f:
                print(*args, file=f, **kwargs)

    def HandleExpr(self, Node: ast.AST, UseSingleQuote: bool = False, VarType: ir.Type | None = None) -> Any:
        return self.ExprHandler.HandleExpr(Node, UseSingleQuote, VarType)
