#!/usr/bin/env python3
import os
import sys
from gi.repository import Gio, GLib

def main():
    # 定义服务常量
    BUS_NAME = "org.deepin.immutable.ReadOnlyAuditor1"
    OBJECT_PATH = "/org/deepin/immutable/ReadOnlyAuditor1"
    INTERFACE_NAME = "org.deepin.immutable.ReadOnlyAuditor1"
    METHOD_NAME = "ExportLog"

    try:
        # 1. 连接到系统总线 (System Bus)
        bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)

        # 2. 创建 DBus 代理对象
        # 使用 new_sync 创建一个同步的代理
        proxy = Gio.DBusProxy.new_sync(
            bus,
            Gio.DBusProxyFlags.NONE,
            None,
            BUS_NAME,
            OBJECT_PATH,
            INTERFACE_NAME,
            None
        )

        print(f"正在调用 {INTERFACE_NAME}.{METHOD_NAME} ...")

        # 3. 调用方法
        # 注意：因为返回值包含文件描述符 (h)，我们需要使用 call_with_unix_fd_list_sync
        # 参数说明：方法名, 参数(GVariant), 标志, 超时(-1默认), 取消对象, fd_list(输入)
        # 返回值：(结果GVariant, 输出的UnixFDList)
        result_variant, out_fd_list = proxy.call_with_unix_fd_list_sync(
            METHOD_NAME,
            None,  # 该方法没有入参
            Gio.DBusCallFlags.NONE,
            -1,
            None,
            None
        )

        # 4. 解析返回值
        # DBus 返回的签名是 (h)，即一个包含 handle 索引的 tuple
        # result_variant.get_child_value(0) 获取第一个返回值
        # .get_handle() 获取在该消息的 FD 列表中的索引位置 (int)
        handle_index = result_variant.get_child_value(0).get_handle()
        
        if out_fd_list is None:
            print("错误：未收到文件描述符列表。")
            sys.exit(1)

        # 5. 从 FD 列表中通过索引获取真实的操作系统文件描述符 (int)
        real_fd = out_fd_list.get(handle_index)

        print(f"成功获取文件描述符: {real_fd}")

        # 6. 读取文件内容
        # 使用 os.fdopen 将文件描述符包装成 Python 的文件对象
        # 注意：C 代码中 unlink 了文件，但只要持有 fd，我们依然可以读取内容
        try:
            with os.fdopen(real_fd, 'r', encoding='utf-8', errors='replace') as f:
                content = f.read()
                print("-" * 20 + " 日志内容 " + "-" * 20)
                if content:
                    print(content)
                else:
                    print("(日志为空)")
                print("-" * 50)
        except OSError as e:
            print(f"读取文件描述符失败: {e}")

    except GLib.Error as e:
        print(f"DBus 调用失败: {e.message}")
        # 这里的错误通常对应 C 代码中的 sd_bus_error_set_errno
    except Exception as e:
        print(f"发生意外错误: {e}")

if __name__ == "__main__":
    main()