import t, c
from stdint import *
import memhub
import string
import stdlib
import viperlib
import hashlib
import w32.win32file
import w32.win32base


# ============================================================
# Utils - 工程工具函数
#
# 提供 SHA1 计算和目录清理等通用工具函数。
# ============================================================

# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr


# ============================================================
# compute_sha1 - 计算字符串的 SHA1，返回前 16 个十六进制字符
#
# 使用 includes/hashlib 库的 sha1 类计算摘要，转为十六进制字符串。
# 参考 Projectrans.py 的 compute_sha1（hashlib.sha1().hexdigest()[:16]）。
# ============================================================
def compute_sha1(pool: memhub.MemBuddy | t.CPtr, content: str) -> str:
    """计算字符串的 SHA1，返回前 16 个十六进制字符（用于文件命名）"""
    if content is None or pool is None:
        return None

    # 构造 sha1 对象（__init__ 会初始化 state/count/buf）
    # ctx 在栈上分配（alloca），函数内使用完即丢弃，无需堆分配
    ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
    if ctx is None:
        return None

    # 计算摘要
    ctx.update(content)
    digest: bytes = pool.alloc(hashlib.SHA1_DIGEST_LEN)
    if digest is None:
        return None
    ctx.final(digest)

    # 转为十六进制字符串（取前 8 字节 = 16 个十六进制字符）
    hex_buf: str = pool.alloc(17)
    if hex_buf is None:
        return None
    for i in range(8):
        hi: int = (digest[i] >> 4) & 0xF
        lo: int = digest[i] & 0xF
        if hi < 10:
            hex_buf[i * 2] = '0' + hi
        else:
            hex_buf[i * 2] = 'a' + (hi - 10)
        if lo < 10:
            hex_buf[i * 2 + 1] = '0' + lo
        else:
            hex_buf[i * 2 + 1] = 'a' + (lo - 10)
    hex_buf[16] = '\0'
    return hex_buf


# ============================================================
# CleanDir - 删除目录中所有文件（非递归，保留目录本身）
#
# 用于 --clean 选项：清理 temp_dir 和 output_dir 中的旧文件。
# ============================================================
def CleanDir(dir_path: str) -> int:
    """删除目录中所有文件（非递归），返回删除的文件数，-1 表示错误"""
    if dir_path is None:
        return -1
    dir_len: t.CSizeT = string.strlen(dir_path)
    pattern: bytes = stdlib.malloc(dir_len + 8)
    if pattern is None:
        return -1
    viperlib.snprintf(pattern, dir_len + 8, "%s/*", dir_path)

    find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__())
    if find_data is None:
        stdlib.free(pattern)
        return -1
    string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__())

    handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data)
    if handle == w32.win32base.INVALID_HANDLE_VALUE:
        stdlib.free(pattern)
        stdlib.free(find_data)
        return 0

    deleted: int = 0
    while 1:
        fname: str = find_data.cFileName
        if fname is not None:
            # 跳过 . 和 ..
            if fname[0] == '.':
                if fname[1] == '\0':
                    fname = None
                elif fname[1] == '.' and fname[2] == '\0':
                    fname = None
        if fname is not None:
            fname_len: t.CSizeT = string.strlen(fname)
            full_path: bytes = stdlib.malloc(dir_len + fname_len + 2)
            if full_path is not None:
                viperlib.snprintf(full_path, dir_len + fname_len + 2, "%s/%s", dir_path, fname)
                if w32.win32file.DeleteFileA(full_path) != 0:
                    deleted += 1
                stdlib.free(full_path)

        if w32.win32file.FindNextFileA(handle, find_data) == 0:
            break

    w32.win32file.FindClose(handle)
    stdlib.free(pattern)
    stdlib.free(find_data)
    return deleted
